Pathauto and dependencies
This commit is contained in:
parent
4b1a293d57
commit
24ffcb956b
257 changed files with 29510 additions and 0 deletions
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Controller;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\token\TreeBuilderInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Returns autocomplete responses for tokens.
|
||||
*/
|
||||
class TokenAutocompleteController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\TreeBuilderInterface
|
||||
*/
|
||||
protected $treeBuilder;
|
||||
|
||||
public function __construct(TreeBuilderInterface $tree_builder) {
|
||||
$this->treeBuilder = $tree_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('token.tree_builder')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves suggestions for block category autocompletion.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The current request.
|
||||
* @param string $token_type
|
||||
* The token type.
|
||||
* @param string $filter
|
||||
* The autocomplete filter.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
* A JSON response containing autocomplete suggestions.
|
||||
*/
|
||||
public function autocomplete($token_type, $filter, Request $request) {
|
||||
$filter = substr($filter, strrpos($filter, '['));
|
||||
|
||||
$matches = array();
|
||||
|
||||
if (!Unicode::strlen($filter)) {
|
||||
$matches["[{$token_type}:"] = 0;
|
||||
}
|
||||
else {
|
||||
$depth = max(1, substr_count($filter, ':'));
|
||||
$tree = $this->treeBuilder->buildTree($token_type, ['flat' => TRUE, 'depth' => $depth]);
|
||||
foreach (array_keys($tree) as $token) {
|
||||
if (strpos($token, $filter) === 0) {
|
||||
$matches[$token] = levenshtein($token, $filter);
|
||||
if (isset($tree[$token]['children'])) {
|
||||
$token = rtrim($token, ':]') . ':';
|
||||
$matches[$token] = levenshtein($token, $filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
asort($matches);
|
||||
|
||||
$keys = array_keys($matches);
|
||||
$matches = array_combine($keys, $keys);
|
||||
|
||||
return new JsonResponse($matches);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
|
||||
/**
|
||||
* Clears cache for tokens.
|
||||
*/
|
||||
class TokenCacheController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Clear caches and redirect back to the frontpage.
|
||||
*/
|
||||
public function flush() {
|
||||
token_clear_cache();
|
||||
drupal_set_message(t('Token registry caches cleared.'));
|
||||
return $this->redirect('<front>');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Controller;
|
||||
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\token\TokenEntityMapperInterface;
|
||||
use Drupal\token\TreeBuilderInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Devel integration for tokens.
|
||||
*/
|
||||
class TokenDevelController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\TreeBuilderInterface
|
||||
*/
|
||||
protected $treeBuilder;
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\TokenEntityMapperInterface
|
||||
*/
|
||||
protected $entityMapper;
|
||||
|
||||
public function __construct(TreeBuilderInterface $tree_builder, TokenEntityMapperInterface $entity_mapper) {
|
||||
$this->treeBuilder = $tree_builder;
|
||||
$this->entityMapper = $entity_mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('token.tree_builder'),
|
||||
$container->get('token.entity_mapper')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the loaded structure of the current entity.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* A RouteMatch object.
|
||||
*
|
||||
* @return array
|
||||
* Array of page elements to render.
|
||||
*/
|
||||
public function entityTokens(RouteMatchInterface $route_match) {
|
||||
$output = [];
|
||||
|
||||
$parameter_name = $route_match->getRouteObject()->getOption('_token_entity_type_id');
|
||||
$entity = $route_match->getParameter($parameter_name);
|
||||
|
||||
if ($entity && $entity instanceof EntityInterface) {
|
||||
$output = $this->renderTokenTree($entity);
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the token tree for the specified entity.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity for which the token tree should be rendered.
|
||||
*
|
||||
* @return array
|
||||
* Render array of the token tree for the $entity.
|
||||
*
|
||||
* @see static::entityLoad
|
||||
*/
|
||||
protected function renderTokenTree(EntityInterface $entity) {
|
||||
$this->moduleHandler()->loadInclude('token', 'pages.inc');
|
||||
$entity_type = $entity->getEntityTypeId();
|
||||
|
||||
$token_type = $this->entityMapper->getTokenTypeForEntityType($entity_type);
|
||||
$options = [
|
||||
'flat' => TRUE,
|
||||
'values' => TRUE,
|
||||
'data' => [$token_type => $entity],
|
||||
];
|
||||
|
||||
$token_tree = [
|
||||
$token_type => [
|
||||
'tokens' => $this->treeBuilder->buildTree($token_type, $options),
|
||||
],
|
||||
];
|
||||
// foreach ($tree as $token => $token_info) {
|
||||
// if (!isset($token_info['value']) && !empty($token_info['parent']) && !isset($tree[$token_info['parent']]['value'])) {
|
||||
// continue;
|
||||
// }
|
||||
// }
|
||||
|
||||
$build['tokens'] = [
|
||||
'#type' => 'token_tree_table',
|
||||
'#show_restricted' => FALSE,
|
||||
'#show_nested' => FALSE,
|
||||
'#skip_empty_values' => TRUE,
|
||||
'#token_tree' => $token_tree,
|
||||
'#columns' => ['token', 'value'],
|
||||
'#empty' => $this->t('No tokens available.'),
|
||||
];
|
||||
|
||||
return $build;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Controller;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\token\TreeBuilderInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* Returns tree responses for tokens.
|
||||
*/
|
||||
class TokenTreeController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\TreeBuilderInterface
|
||||
*/
|
||||
protected $treeBuilder;
|
||||
|
||||
public function __construct(TreeBuilderInterface $tree_builder) {
|
||||
$this->treeBuilder = $tree_builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('token.tree_builder')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Page callback to output a token tree as an empty page.
|
||||
*/
|
||||
function outputTree(Request $request) {
|
||||
$options = $request->query->has('options') ? Json::decode($request->query->get('options')) : [];
|
||||
|
||||
// The option token_types may only be an array OR 'all'. If it is not set,
|
||||
// we assume that only global token types are requested.
|
||||
$token_types = !empty($options['token_types']) ? $options['token_types'] : [];
|
||||
if ($token_types == 'all') {
|
||||
$build = $this->treeBuilder->buildAllRenderable($options);
|
||||
}
|
||||
else {
|
||||
$build = $this->treeBuilder->buildRenderable($token_types, $options);
|
||||
}
|
||||
|
||||
$build['#cache']['contexts'][] = 'url.query_args:options';
|
||||
$build['#title'] = $this->t('Available tokens');
|
||||
|
||||
return $build;
|
||||
}
|
||||
|
||||
}
|
||||
155
web/modules/contrib/token/src/Element/TokenTreeTable.php
Normal file
155
web/modules/contrib/token/src/Element/TokenTreeTable.php
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Element;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Core\Render\Element\Table;
|
||||
|
||||
/**
|
||||
* Provides a render element for a token tree table.
|
||||
*
|
||||
* @RenderElement("token_tree_table")
|
||||
*/
|
||||
class TokenTreeTable extends Table {
|
||||
|
||||
protected static $cssFilter = [' ' => '-', '_' => '-', '/' => '-', '[' => '-', ']' => '', ':' => '--', '?' => '', '<' => '-', '>' => '-'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
$class = get_class($this);
|
||||
return [
|
||||
'#header' => [],
|
||||
'#rows' => [],
|
||||
'#token_tree' => [],
|
||||
'#columns' => ['name', 'token', 'description'],
|
||||
'#empty' => '',
|
||||
'#show_restricted' => FALSE,
|
||||
'#show_nested' => FALSE,
|
||||
'#skip_empty_values' => FALSE,
|
||||
'#click_insert' => TRUE,
|
||||
'#sticky' => FALSE,
|
||||
'#responsive' => TRUE,
|
||||
'#input' => FALSE,
|
||||
'#pre_render' => [
|
||||
[$class, 'preRenderTokenTree'],
|
||||
[$class, 'preRenderTable'],
|
||||
],
|
||||
'#theme' => 'table__token_tree',
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'token/token',
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-render the token tree to transform rows in the token tree.
|
||||
*
|
||||
* @param array $element
|
||||
*
|
||||
* @return array
|
||||
* The processed element.
|
||||
*/
|
||||
public static function preRenderTokenTree($element) {
|
||||
$multiple_token_types = count($element['#token_tree']) > 1;
|
||||
foreach ($element['#token_tree'] as $token_type => $type_info) {
|
||||
// Do not show nested tokens.
|
||||
if (!empty($type_info['nested']) && empty($element['#show_nested'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($multiple_token_types) {
|
||||
$row = static::formatRow($token_type, $type_info, $element['#columns'], TRUE);
|
||||
$element['#rows'][] = $row;
|
||||
}
|
||||
|
||||
foreach ($type_info['tokens'] as $token => $token_info) {
|
||||
if (!empty($token_info['restricted']) && empty($element['#show_restricted'])) {
|
||||
continue;
|
||||
}
|
||||
if ($element['#skip_empty_values'] && empty($token_info['value']) && !empty($token_info['parent']) && !isset($tree[$token_info['parent']]['value'])) {
|
||||
continue;
|
||||
}
|
||||
if ($multiple_token_types && !isset($token_info['parent'])) {
|
||||
$token_info['parent'] = $token_type;
|
||||
}
|
||||
$row = static::formatRow($token, $token_info, $element['#columns']);
|
||||
$element['#rows'][] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($element['#rows'])) {
|
||||
$element['#attached']['library'][] = 'token/jquery.treeTable';
|
||||
}
|
||||
|
||||
// Fill headers if one is not specified.
|
||||
if (empty($element['#header'])) {
|
||||
$column_map = [
|
||||
'name' => t('Name'),
|
||||
'token' => t('Token'),
|
||||
'value' => t('Value'),
|
||||
'description' => t('Description'),
|
||||
];
|
||||
foreach ($element['#columns'] as $col) {
|
||||
$element['#header'][] = $column_map[$col];
|
||||
}
|
||||
}
|
||||
|
||||
$element['#attributes']['class'][] = 'token-tree';
|
||||
|
||||
if ($element['#click_insert']) {
|
||||
$element['#caption'] = t('Click a token to insert it into the field you\'ve last clicked.');
|
||||
$element['#attributes']['class'][] = 'token-click-insert';
|
||||
}
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
protected static function cleanCssIdentifier($id) {
|
||||
return 'token-' . Html::cleanCssIdentifier(trim($id, '[]'), static::$cssFilter);
|
||||
}
|
||||
|
||||
protected static function formatRow($token, $token_info, $columns, $is_group = FALSE) {
|
||||
$row = [
|
||||
'id' => static::cleanCssIdentifier($token),
|
||||
'data-tt-id' => static::cleanCssIdentifier($token),
|
||||
'class' => [],
|
||||
'data' => [],
|
||||
];
|
||||
|
||||
foreach ($columns as $col) {
|
||||
switch ($col) {
|
||||
case 'name':
|
||||
$row['data'][$col] = $token_info['name'];
|
||||
break;
|
||||
|
||||
case 'token':
|
||||
$row['data'][$col]['data'] = $token;
|
||||
$row['data'][$col]['class'][] = 'token-key';
|
||||
break;
|
||||
|
||||
case 'description':
|
||||
$row['data'][$col] = isset($token_info['description']) ? $token_info['description'] : '';
|
||||
break;
|
||||
|
||||
case 'value':
|
||||
$row['data'][$col] = !$is_group && isset($token_info['value']) ? $token_info['value'] : '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($is_group) {
|
||||
// This is a token type/group.
|
||||
$row['class'][] = 'token-group';
|
||||
}
|
||||
elseif (!empty($token_info['parent'])) {
|
||||
$row['data-tt-parent-id'] = static::cleanCssIdentifier($token_info['parent']);
|
||||
unset($row['parent']);
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Plugin\Derivative;
|
||||
|
||||
use Drupal\Component\Plugin\Derivative\DeriverBase;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
class DevelLocalTask extends DeriverBase implements ContainerDeriverInterface {
|
||||
|
||||
use StringTranslationTrait;
|
||||
|
||||
protected $entityTypeManager;
|
||||
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, TranslationInterface $string_translation) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->stringTranslation = $string_translation;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function create(ContainerInterface $container, $base_plugin_id) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('string_translation')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDerivativeDefinitions($base_plugin_definition) {
|
||||
$this->derivatives = [];
|
||||
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
if ($entity_type->hasLinkTemplate('token-devel')) {
|
||||
$this->derivatives["$entity_type_id.token_devel_tab"] = [
|
||||
'route_name' => "entity.$entity_type_id.token_devel",
|
||||
'weight' => 110,
|
||||
'title' => $this->t('Tokens'),
|
||||
'parent_id' => "devel.entities:$entity_type_id.devel_tab",
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->derivatives as &$entry) {
|
||||
$entry += $base_plugin_definition;
|
||||
}
|
||||
|
||||
return $this->derivatives;
|
||||
}
|
||||
}
|
||||
74
web/modules/contrib/token/src/Routing/RouteSubscriber.php
Normal file
74
web/modules/contrib/token/src/Routing/RouteSubscriber.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Routing;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
use Drupal\Core\Routing\RouteSubscriberBase;
|
||||
use Drupal\Core\Routing\RoutingEvents;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Subscriber for Devel routes.
|
||||
*/
|
||||
class RouteSubscriber extends RouteSubscriberBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function alterRoutes(RouteCollection $collection) {
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
if ($devel_render = $entity_type->getLinkTemplate('token-devel')) {
|
||||
$options = [
|
||||
'_admin_route' => TRUE,
|
||||
'_token_entity_type_id' => $entity_type_id,
|
||||
'parameters' => [
|
||||
$entity_type_id => [
|
||||
'type' => 'entity:' . $entity_type_id,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$route = new Route(
|
||||
$devel_render,
|
||||
[
|
||||
'_controller' => '\Drupal\token\Controller\TokenDevelController::entityTokens',
|
||||
'_title' => 'Devel Tokens',
|
||||
],
|
||||
[
|
||||
'_permission' => 'access devel information',
|
||||
'_module_dependencies' => 'devel',
|
||||
],
|
||||
$options
|
||||
);
|
||||
|
||||
$collection->add("entity.$entity_type_id.token_devel", $route);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getSubscribedEvents() {
|
||||
$events = parent::getSubscribedEvents();
|
||||
$events[RoutingEvents::ALTER] = array('onAlterRoutes', 100);
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
72
web/modules/contrib/token/src/Tests/TokenBlockTest.php
Normal file
72
web/modules/contrib/token/src/Tests/TokenBlockTest.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
use Drupal\block_content\Entity\BlockContent;
|
||||
use Drupal\block_content\Entity\BlockContentType;
|
||||
|
||||
/**
|
||||
* Tests block tokens.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenBlockTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'node', 'views', 'block_content'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp($modules = array()) {
|
||||
parent::setUp();
|
||||
$this->admin_user = $this->drupalCreateUser(array('access content', 'administer blocks'));
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
public function testBlockTitleTokens() {
|
||||
$label = 'tokenblock';
|
||||
$bundle = BlockContentType::create(array(
|
||||
'id' => $label,
|
||||
'label' => $label,
|
||||
'revision' => FALSE
|
||||
));
|
||||
$bundle->save();
|
||||
|
||||
$block_content = BlockContent::create(array(
|
||||
'type' => $label,
|
||||
'label' => '[current-page:title] block title',
|
||||
'info' => 'Test token title block',
|
||||
'body[value]' => 'This is the test token title block.',
|
||||
));
|
||||
$block_content->save();
|
||||
|
||||
$block = $this->drupalPlaceBlock('block_content:' . $block_content->uuid(), array(
|
||||
'label' => '[user:name]',
|
||||
));
|
||||
$this->drupalGet($block->urlInfo());
|
||||
// Ensure that the link to available tokens is present and correctly
|
||||
// positioned.
|
||||
$this->assertLink('Browse available tokens.');
|
||||
$this->assertText('This field supports tokens. Browse available tokens.');
|
||||
$this->drupalPostForm(NULL, array(), t('Save block'));
|
||||
// Ensure token validation is working on the block.
|
||||
$this->assertText('Title is using the following invalid tokens: [user:name].');
|
||||
|
||||
// Create the block for real now with a valid title.
|
||||
$settings = $block->get('settings');
|
||||
$settings['label'] = '[current-page:title] block title';
|
||||
$block->set('settings', $settings);
|
||||
$block->save();
|
||||
|
||||
// Ensure that tokens are not double-escaped when output as a block title.
|
||||
$this->drupalCreateContentType(array('type' => 'page'));
|
||||
$node = $this->drupalCreateNode(array('title' => "Site's first node"));
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
// The apostraphe should only be escaped once.
|
||||
$this->assertRaw("Site's first node block title");
|
||||
}
|
||||
}
|
||||
66
web/modules/contrib/token/src/Tests/TokenCurrentPageTest.php
Normal file
66
web/modules/contrib/token/src/Tests/TokenCurrentPageTest.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Test the [current-page:*] tokens.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenCurrentPageTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
function testCurrentPageTokens() {
|
||||
$tokens = array(
|
||||
'[current-page:title]' => t('Log in'),
|
||||
'[current-page:url]' => Url::fromRoute('user.login', [], array('absolute' => TRUE))->toString(),
|
||||
'[current-page:url:absolute]' => Url::fromRoute('user.login', [], array('absolute' => TRUE))->toString(),
|
||||
'[current-page:url:relative]' => Url::fromRoute('user.login')->toString(),
|
||||
'[current-page:url:path]' => '/user/login',
|
||||
'[current-page:url:args:value:0]' => 'user',
|
||||
'[current-page:url:args:value:1]' => 'login',
|
||||
'[current-page:url:args:value:2]' => NULL,
|
||||
'[current-page:url:unaliased]' => Url::fromRoute('user.login', [], array('absolute' => TRUE, 'alias' => TRUE))->toString(),
|
||||
'[current-page:page-number]' => 1,
|
||||
'[current-page:query:foo]' => NULL,
|
||||
'[current-page:query:bar]' => NULL,
|
||||
// Deprecated tokens
|
||||
'[current-page:arg:0]' => 'user',
|
||||
'[current-page:arg:1]' => 'login',
|
||||
'[current-page:arg:2]' => NULL,
|
||||
);
|
||||
$this->assertPageTokens('user/login', $tokens);
|
||||
|
||||
$this->drupalCreateContentType(array('type' => 'page'));
|
||||
$node = $this->drupalCreateNode(array('title' => 'Node title', 'path' => array('alias' => '/node-alias')));
|
||||
$tokens = array(
|
||||
'[current-page:title]' => 'Node title',
|
||||
'[current-page:url]' => $node->url('canonical', array('absolute' => TRUE)),
|
||||
'[current-page:url:absolute]' => $node->url('canonical', array('absolute' => TRUE)),
|
||||
'[current-page:url:relative]' => $node->url(),
|
||||
'[current-page:url:alias]' => '/node-alias',
|
||||
'[current-page:url:args:value:0]' => 'node-alias',
|
||||
'[current-page:url:args:value:1]' => NULL,
|
||||
'[current-page:url:unaliased]' => $node->url('canonical', array('absolute' => TRUE, 'alias' => TRUE)),
|
||||
'[current-page:url:unaliased:args:value:0]' => 'node',
|
||||
'[current-page:url:unaliased:args:value:1]' => $node->id(),
|
||||
'[current-page:url:unaliased:args:value:2]' => NULL,
|
||||
'[current-page:page-number]' => 1,
|
||||
'[current-page:query:foo]' => 'bar',
|
||||
'[current-page:query:bar]' => NULL,
|
||||
// Deprecated tokens
|
||||
'[current-page:arg:0]' => 'node',
|
||||
'[current-page:arg:1]' => 1,
|
||||
'[current-page:arg:2]' => NULL,
|
||||
);
|
||||
$this->assertPageTokens("/node/{$node->id()}", $tokens, array(), array('url_options' => array('query' => array('foo' => 'bar'))));
|
||||
}
|
||||
}
|
||||
280
web/modules/contrib/token/src/Tests/TokenFieldUiTest.php
Normal file
280
web/modules/contrib/token/src/Tests/TokenFieldUiTest.php
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\image\Entity\ImageStyle;
|
||||
|
||||
/**
|
||||
* Tests field ui.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenFieldUiTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['field_ui', 'node', 'image'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp($modules = []) {
|
||||
parent::setUp();
|
||||
$this->adminUser = $this->drupalCreateUser(['administer content types', 'administer node fields']);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
'description' => "Use <em>articles</em> for time-sensitive content like news, press releases or blog posts.",
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => 'field_body',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text_with_summary',
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'field_name' => 'field_body',
|
||||
'label' => 'Body',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'article',
|
||||
))->save();
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => 'field_image',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'image',
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'field_name' => 'field_image',
|
||||
'label' => 'Image',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'article',
|
||||
))->save();
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => 'field_image_2',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'image',
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'field_name' => 'field_image_2',
|
||||
'label' => 'Image 2',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'article',
|
||||
))->save();
|
||||
entity_create('field_storage_config', array(
|
||||
'field_name' => 'multivalued_field_image',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'image',
|
||||
))->save();
|
||||
entity_create('field_config', array(
|
||||
'field_name' => 'multivalued_field_image',
|
||||
'label' => 'Multivalued field image',
|
||||
'entity_type' => 'node',
|
||||
'bundle' => 'article',
|
||||
))->save();
|
||||
|
||||
entity_get_form_display('node', 'article', 'default')
|
||||
->setComponent('field_body', [
|
||||
'type' => 'text_textarea_with_summary',
|
||||
'settings' => [
|
||||
'rows' => '9',
|
||||
'summary_rows' => '3',
|
||||
],
|
||||
'weight' => 5,
|
||||
])
|
||||
->save();
|
||||
}
|
||||
|
||||
public function testFileFieldUi() {
|
||||
$this->drupalGet('admin/structure/types/manage/article/fields/node.article.field_image');
|
||||
|
||||
// Ensure the 'Browse available tokens' link is present and correct.
|
||||
$this->assertLink('Browse available tokens.');
|
||||
$this->assertLinkByHref('token/tree');
|
||||
|
||||
// Ensure that the default file directory value validates correctly.
|
||||
$this->drupalPostForm(NULL, [], t('Save settings'));
|
||||
$this->assertText(t('Saved Image configuration.'));
|
||||
}
|
||||
|
||||
public function testFieldDescriptionTokens() {
|
||||
$edit = [
|
||||
'description' => 'The site is called [site:name].',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/types/manage/article/fields/node.article.field_body', $edit, 'Save settings');
|
||||
|
||||
$this->drupalGet('node/add/article');
|
||||
$this->assertText('The site is called Drupal.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that tokens are correctly provided and replaced for the image fields.
|
||||
*/
|
||||
public function testImageFieldTokens() {
|
||||
// Generate 2 different test images.
|
||||
file_unmanaged_copy(\Drupal::root() . '/core/misc/druplicon.png', 'public://example1.png');
|
||||
file_unmanaged_copy(\Drupal::root() . '/core/misc/loading.gif', 'public://example2.gif');
|
||||
|
||||
// Resize the test images so that they will be scaled down during token
|
||||
// replacement.
|
||||
$image1 = \Drupal::service('image.factory')->get('public://example1.png');
|
||||
$image1->resize(500, 500);
|
||||
$image1->save();
|
||||
$image2 = \Drupal::service('image.factory')->get('public://example2.gif');
|
||||
$image2->resize(500, 500);
|
||||
$image2->save();
|
||||
|
||||
/** @var \Drupal\file\Entity\File $image1 */
|
||||
$image1 = File::create(['uri' => 'public://example1.png']);
|
||||
$image1->save();
|
||||
/** @var \Drupal\file\Entity\File $image2 */
|
||||
$image2 = File::create(['uri' => 'public://example2.gif']);
|
||||
$image2->save();
|
||||
|
||||
$node = Node::create([
|
||||
'title' => 'Test node title',
|
||||
'type' => 'article',
|
||||
'field_image' => [
|
||||
[
|
||||
'target_id' => $image1->id(),
|
||||
],
|
||||
],
|
||||
'field_image_2' => [
|
||||
[
|
||||
'target_id' => $image2->id(),
|
||||
],
|
||||
],
|
||||
'multivalued_field_image' => [
|
||||
['target_id' => $image1->id()],
|
||||
['target_id' => $image2->id()],
|
||||
],
|
||||
]);
|
||||
$node->save();
|
||||
|
||||
// Obtain the file size and dimension of the images that will be scaled
|
||||
// down during token replacement by applying the styles here.
|
||||
$style_thumbnail = ImageStyle::load('thumbnail');
|
||||
$style_thumbnail->createDerivative('public://example1.png', 'public://styles/thumbnail/public/example1-test.png');
|
||||
$style_thumbnail->createDerivative('public://example2.gif', 'public://styles/thumbnail/public/example2-test.gif');
|
||||
$image_1_thumbnail = \Drupal::service('image.factory')->get('public://styles/thumbnail/public/example1-test.png');
|
||||
$image_2_thumbnail = \Drupal::service('image.factory')->get('public://styles/thumbnail/public/example2-test.gif');
|
||||
$style_medium = ImageStyle::load('medium');
|
||||
$style_medium->createDerivative('public://example1.png', 'public://styles/medium/public/example1-test.png');
|
||||
$style_medium->createDerivative('public://example2.gif', 'public://styles/medium/public/example2-test.gif');
|
||||
$image_1_medium = \Drupal::service('image.factory')->get('public://styles/medium/public/example1-test.png');
|
||||
$image_2_medium = \Drupal::service('image.factory')->get('public://styles/medium/public/example2-test.gif');
|
||||
$style_large = ImageStyle::load('large');
|
||||
$style_large->createDerivative('public://example1.png', 'public://styles/large/public/example1-test.png');
|
||||
$style_large->createDerivative('public://example2.gif', 'public://styles/large/public/example2-test.gif');
|
||||
$image_1_large = \Drupal::service('image.factory')->get('public://styles/large/public/example1-test.png');
|
||||
$image_2_large = \Drupal::service('image.factory')->get('public://styles/large/public/example2-test.gif');
|
||||
|
||||
// Delete the image derivatives, to make sure they are re-created.
|
||||
unlink('public://styles/thumbnail/public/example1-test.png');
|
||||
unlink('public://styles/medium/public/example1-test.png');
|
||||
unlink('public://styles/large/public/example1-test.png');
|
||||
unlink('public://styles/thumbnail/public/example2-test.gif');
|
||||
unlink('public://styles/medium/public/example2-test.gif');
|
||||
unlink('public://styles/large/public/example2-test.gif');
|
||||
|
||||
$tokens = [
|
||||
// field_image
|
||||
'field_image:thumbnail:mimetype' => 'image/png',
|
||||
'field_image:medium:mimetype' => 'image/png',
|
||||
'field_image:large:mimetype' => 'image/png',
|
||||
'field_image:thumbnail:filesize' => $image_1_thumbnail->getFileSize(),
|
||||
'field_image:medium:filesize' => $image_1_medium->getFileSize(),
|
||||
'field_image:large:filesize' => $image_1_large->getFileSize(),
|
||||
'field_image:thumbnail:height' => '100',
|
||||
'field_image:medium:height' => '220',
|
||||
'field_image:large:height' => '480',
|
||||
'field_image:thumbnail:width' => '100',
|
||||
'field_image:medium:width' => '220',
|
||||
'field_image:large:width' => '480',
|
||||
'field_image:thumbnail:uri' => 'public://styles/thumbnail/public/example1.png',
|
||||
'field_image:medium:uri' => 'public://styles/medium/public/example1.png',
|
||||
'field_image:large:uri' => 'public://styles/large/public/example1.png',
|
||||
'field_image:thumbnail:url' => $style_thumbnail->buildUrl('public://example1.png'),
|
||||
'field_image:medium:url' => $style_medium->buildUrl('public://example1.png'),
|
||||
'field_image:large:url' => $style_large->buildUrl('public://example1.png'),
|
||||
'field_image:thumbnail' => $style_thumbnail->buildUrl('public://example1.png'),
|
||||
'field_image:medium' => $style_medium->buildUrl('public://example1.png'),
|
||||
'field_image:large' => $style_large->buildUrl('public://example1.png'),
|
||||
// field_image_2
|
||||
'field_image_2:thumbnail:mimetype' => 'image/gif',
|
||||
'field_image_2:medium:mimetype' => 'image/gif',
|
||||
'field_image_2:large:mimetype' => 'image/gif',
|
||||
'field_image_2:thumbnail:filesize' => $image_2_thumbnail->getFileSize(),
|
||||
'field_image_2:medium:filesize' => $image_2_medium->getFileSize(),
|
||||
'field_image_2:large:filesize' => $image_2_large->getFileSize(),
|
||||
'field_image_2:thumbnail:height' => '100',
|
||||
'field_image_2:medium:height' => '220',
|
||||
'field_image_2:large:height' => '480',
|
||||
'field_image_2:thumbnail:width' => '100',
|
||||
'field_image_2:medium:width' => '220',
|
||||
'field_image_2:large:width' => '480',
|
||||
'field_image_2:thumbnail:uri' => 'public://styles/thumbnail/public/example2.gif',
|
||||
'field_image_2:medium:uri' => 'public://styles/medium/public/example2.gif',
|
||||
'field_image_2:large:uri' => 'public://styles/large/public/example2.gif',
|
||||
'field_image_2:thumbnail:url' => $style_thumbnail->buildUrl('public://example2.gif'),
|
||||
'field_image_2:medium:url' => $style_medium->buildUrl('public://example2.gif'),
|
||||
'field_image_2:large:url' => $style_large->buildUrl('public://example2.gif'),
|
||||
'field_image_2:thumbnail' => $style_thumbnail->buildUrl('public://example2.gif'),
|
||||
'field_image_2:medium' => $style_medium->buildUrl('public://example2.gif'),
|
||||
'field_image_2:large' => $style_large->buildUrl('public://example2.gif'),
|
||||
// multivalued_field_image:0, test for thumbnail image style only.
|
||||
'multivalued_field_image:0:thumbnail:mimetype' => 'image/png',
|
||||
'multivalued_field_image:0:thumbnail:filesize' => $image_1_thumbnail->getFileSize(),
|
||||
'multivalued_field_image:0:thumbnail:height' => '100',
|
||||
'multivalued_field_image:0:thumbnail:width' => '100',
|
||||
'multivalued_field_image:0:thumbnail:uri' => 'public://styles/thumbnail/public/example1.png',
|
||||
'multivalued_field_image:0:thumbnail:url' => $style_thumbnail->buildUrl('public://example1.png'),
|
||||
'multivalued_field_image:0:thumbnail' => $style_thumbnail->buildUrl('public://example1.png'),
|
||||
// multivalued_field_image:1, test for medium image style only.
|
||||
'multivalued_field_image:1:medium:mimetype' => 'image/gif',
|
||||
'multivalued_field_image:1:medium:filesize' => $image_2_medium->getFileSize(),
|
||||
'multivalued_field_image:1:medium:height' => '220',
|
||||
'multivalued_field_image:1:medium:width' => '220',
|
||||
'multivalued_field_image:1:medium:uri' => 'public://styles/medium/public/example2.gif',
|
||||
'multivalued_field_image:1:medium:url' => $style_medium->buildUrl('public://example2.gif'),
|
||||
'multivalued_field_image:1:medium' => $style_medium->buildUrl('public://example2.gif'),
|
||||
];
|
||||
$this->assertTokens('node', ['node' => $node], $tokens);
|
||||
|
||||
/** @var \Drupal\token\Token $token_service */
|
||||
$token_service = \Drupal::service('token');
|
||||
|
||||
// Test one of the image style's token info for cardinality 1 image field.
|
||||
$token_info = $token_service->getTokenInfo('node-field_image', 'thumbnail');
|
||||
$this->assertEqual('Thumbnail (100×100)', $token_info['name']);
|
||||
$this->assertEqual('Represents the image in the given image style.', $token_info['description']);
|
||||
|
||||
// Test one of the image style's token info for a multivalued image field.
|
||||
$token_info = $token_service->getTokenInfo('node-multivalued_field_image', 'medium');
|
||||
$this->assertEqual('Medium (220×220)', $token_info['name']);
|
||||
$this->assertEqual('Represents the image in the given image style.', $token_info['description']);
|
||||
|
||||
// Test few of the image styles' properties token info.
|
||||
$token_info = $token_service->getTokenInfo('image_with_image_style', 'mimetype');
|
||||
$this->assertEqual('MIME type', $token_info['name']);
|
||||
$this->assertEqual('The MIME type (image/png, image/bmp, etc.) of the image.', $token_info['description']);
|
||||
|
||||
$token_info = $token_service->getTokenInfo('image_with_image_style', 'filesize');
|
||||
$this->assertEqual('File size', $token_info['name']);
|
||||
$this->assertEqual('The file size of the image.', $token_info['description']);
|
||||
}
|
||||
|
||||
}
|
||||
459
web/modules/contrib/token/src/Tests/TokenMenuTest.php
Normal file
459
web/modules/contrib/token/src/Tests/TokenMenuTest.php
Normal file
|
|
@ -0,0 +1,459 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\node\Entity\Node;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\system\Entity\Menu;
|
||||
use Drupal\menu_link_content\Entity\MenuLinkContent;
|
||||
|
||||
/**
|
||||
* Tests menu tokens.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenMenuTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [
|
||||
'menu_ui',
|
||||
'node',
|
||||
'block',
|
||||
'language',
|
||||
'block_content',
|
||||
'content_translation',
|
||||
];
|
||||
|
||||
function testMenuTokens() {
|
||||
// Make sure we have a body field on the node type.
|
||||
$this->drupalCreateContentType(['type' => 'page']);
|
||||
// Add a menu.
|
||||
$menu = entity_create('menu', array(
|
||||
'id' => 'main-menu',
|
||||
'label' => 'Main menu',
|
||||
'description' => 'The <em>Main</em> menu is used on many sites to show the major sections of the site, often in a top navigation bar.',
|
||||
));
|
||||
$menu->save();
|
||||
|
||||
// Place the menu block.
|
||||
$this->drupalPlaceBlock('system_menu_block:main-menu');
|
||||
|
||||
// Add a root link.
|
||||
/** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $root_link */
|
||||
$root_link = entity_create('menu_link_content', array(
|
||||
'link' => ['uri' => 'internal:/admin'],
|
||||
'title' => 'Administration',
|
||||
'menu_name' => 'main-menu',
|
||||
));
|
||||
$root_link->save();
|
||||
|
||||
// Add another link with the root link as the parent.
|
||||
/** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $parent_link */
|
||||
$parent_link = entity_create('menu_link_content', array(
|
||||
'link' => ['uri' => 'internal:/admin/config'],
|
||||
'title' => 'Configuration',
|
||||
'menu_name' => 'main-menu',
|
||||
'parent' => $root_link->getPluginId(),
|
||||
));
|
||||
$parent_link->save();
|
||||
|
||||
// Test menu link tokens.
|
||||
$tokens = array(
|
||||
'id' => $parent_link->getPluginId(),
|
||||
'title' => 'Configuration',
|
||||
'menu' => 'Main menu',
|
||||
'menu:name' => 'Main menu',
|
||||
'menu:machine-name' => $menu->id(),
|
||||
'menu:description' => 'The <em>Main</em> menu is used on many sites to show the major sections of the site, often in a top navigation bar.',
|
||||
'menu:menu-link-count' => '2',
|
||||
'menu:edit-url' => Url::fromRoute('entity.menu.edit_form', ['menu' => 'main-menu'], array('absolute' => TRUE))->toString(),
|
||||
'url' => Url::fromRoute('system.admin_config', [], array('absolute' => TRUE))->toString(),
|
||||
'url:absolute' => Url::fromRoute('system.admin_config', [], array('absolute' => TRUE))->toString(),
|
||||
'url:relative' => Url::fromRoute('system.admin_config', [], array('absolute' => FALSE))->toString(),
|
||||
'url:path' => '/admin/config',
|
||||
'url:alias' => '/admin/config',
|
||||
'edit-url' => Url::fromRoute('entity.menu_link_content.canonical', ['menu_link_content' => $parent_link->id()], array('absolute' => TRUE))->toString(),
|
||||
'parent' => 'Administration',
|
||||
'parent:id' => $root_link->getPluginId(),
|
||||
'parent:title' => 'Administration',
|
||||
'parent:menu' => 'Main menu',
|
||||
'parent:parent' => NULL,
|
||||
'parents' => 'Administration',
|
||||
'parents:count' => 1,
|
||||
'parents:keys' => $root_link->getPluginId(),
|
||||
'root' => 'Administration',
|
||||
'root:id' => $root_link->getPluginId(),
|
||||
'root:parent' => NULL,
|
||||
'root:root' => NULL,
|
||||
);
|
||||
$this->assertTokens('menu-link', array('menu-link' => $parent_link), $tokens);
|
||||
|
||||
// Add a node.
|
||||
$node = $this->drupalCreateNode();
|
||||
|
||||
// Allow main menu for this node type.
|
||||
//$this->config('menu.entity.node.' . $node->getType())->set('available_menus', array('main-menu'))->save();
|
||||
|
||||
// Add a node menu link.
|
||||
/** @var \Drupal\menu_link_content\Plugin\Menu\MenuLinkContent $node_link */
|
||||
$node_link = entity_create('menu_link_content', array(
|
||||
'link' => ['uri' =>'entity:node/' . $node->id()],
|
||||
'title' => 'Node link',
|
||||
'parent' => $parent_link->getPluginId(),
|
||||
'menu_name' => 'main-menu',
|
||||
));
|
||||
$node_link->save();
|
||||
|
||||
// Test [node:menu] tokens.
|
||||
$tokens = array(
|
||||
'menu-link' => 'Node link',
|
||||
'menu-link:id' => $node_link->getPluginId(),
|
||||
'menu-link:title' => 'Node link',
|
||||
'menu-link:menu' => 'Main menu',
|
||||
'menu-link:url' => $node->url('canonical', ['absolute' => TRUE]),
|
||||
'menu-link:url:path' => '/node/' . $node->id(),
|
||||
'menu-link:edit-url' => $node_link->url('edit-form', ['absolute' => TRUE]),
|
||||
'menu-link:parent' => 'Configuration',
|
||||
'menu-link:parent:id' => $parent_link->getPluginId(),
|
||||
'menu-link:parents' => 'Administration, Configuration',
|
||||
'menu-link:parents:count' => 2,
|
||||
'menu-link:parents:keys' => $root_link->getPluginId() . ', ' . $parent_link->getPluginId(),
|
||||
'menu-link:root' => 'Administration',
|
||||
'menu-link:root:id' => $root_link->getPluginId(),
|
||||
);
|
||||
$this->assertTokens('node', array('node' => $node), $tokens);
|
||||
|
||||
// Reload the node which will not have $node->menu defined and re-test.
|
||||
$loaded_node = Node::load($node->id());
|
||||
$this->assertTokens('node', array('node' => $loaded_node), $tokens);
|
||||
|
||||
// Regression test for http://drupal.org/node/1317926 to ensure the
|
||||
// original node object is not changed when calling menu_node_prepare().
|
||||
$this->assertTrue(!isset($loaded_node->menu), t('The $node->menu property was not modified during token replacement.'), 'Regression');
|
||||
|
||||
// Now add a node with a menu-link from the UI and ensure it works.
|
||||
$this->drupalLogin($this->drupalCreateUser([
|
||||
'create page content',
|
||||
'edit any page content',
|
||||
'administer menu',
|
||||
'administer nodes',
|
||||
'administer content types',
|
||||
'access administration pages',
|
||||
]));
|
||||
// Setup node type menu options.
|
||||
$edit = array(
|
||||
'menu_options[main-menu]' => 1,
|
||||
'menu_options[main]' => 1,
|
||||
'menu_parent' => 'main-menu:',
|
||||
);
|
||||
$this->drupalPostForm('admin/structure/types/manage/page', $edit, t('Save content type'));
|
||||
|
||||
// Use a menu-link token in the body.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->drupalPostForm(NULL, [
|
||||
// This should get replaced on save.
|
||||
// @see token_module_test_node_presave()
|
||||
'title[0][value]' => 'Node menu title test',
|
||||
'body[0][value]' => 'This is a [node:menu-link:title] token to the menu link title',
|
||||
'menu[enabled]' => 1,
|
||||
'menu[title]' => 'Test preview',
|
||||
], t('Save and publish'));
|
||||
$node = $this->drupalGetNodeByTitle('Node menu title test');
|
||||
$this->assertEqual('This is a Test preview token to the menu link title', $node->body->value);
|
||||
|
||||
// Disable the menu link, save the node and verify that the menu link is
|
||||
// no longer displayed.
|
||||
$link = menu_ui_get_menu_link_defaults($node);
|
||||
$this->drupalPostForm('admin/structure/menu/manage/main-menu', ['links[menu_plugin_id:' . $link['id'] . '][enabled]' => FALSE], t('Save'));
|
||||
$this->assertText('Menu Main menu has been updated.');
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', [], t('Save and keep published'));
|
||||
$this->assertNoLink('Test preview');
|
||||
|
||||
// Now test a parent link and token.
|
||||
$this->drupalGet('node/add/page');
|
||||
// Make sure that the previous node save didn't result in two menu-links
|
||||
// being created by the computed menu-link ER field.
|
||||
// @see token_entity_base_field_info()
|
||||
// @see token_node_menu_link_submit()
|
||||
$selects = $this->cssSelect('select[name="menu[menu_parent]"]');
|
||||
$select = reset($selects);
|
||||
$options = $this->getAllOptions($select);
|
||||
// Filter to items with title containing 'Test preview'.
|
||||
$options = array_filter($options, function(\SimpleXMLElement $item) {
|
||||
return strpos((string) $item[0], 'Test preview') !== FALSE;
|
||||
});
|
||||
$this->assertEqual(1, count($options));
|
||||
$this->drupalPostForm(NULL, [
|
||||
'title[0][value]' => 'Node menu title parent path test',
|
||||
'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
|
||||
'menu[enabled]' => 1,
|
||||
'menu[title]' => 'Child link',
|
||||
'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId(),
|
||||
], t('Save and publish'));
|
||||
$node = $this->drupalGetNodeByTitle('Node menu title parent path test');
|
||||
$this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value);
|
||||
|
||||
// Now edit the node and update the parent and title.
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', [
|
||||
'menu[menu_parent]' => 'main-menu:' . $node_link->getPluginId(),
|
||||
'title[0][value]' => 'Node menu title edit parent path test',
|
||||
'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
|
||||
], t('Save and keep published'));
|
||||
$node = $this->drupalGetNodeByTitle('Node menu title edit parent path test', TRUE);
|
||||
$this->assertEqual(sprintf('This is a /node/%d token to the menu link parent', $loaded_node->id()), $node->body->value);
|
||||
|
||||
// Make sure that the previous node edit didn't result in two menu-links
|
||||
// being created by the computed menu-link ER field.
|
||||
// @see token_entity_base_field_info()
|
||||
// @see token_node_menu_link_submit()
|
||||
$this->drupalGet('node/add/page');
|
||||
$selects = $this->cssSelect('select[name="menu[menu_parent]"]');
|
||||
$select = reset($selects);
|
||||
$options = $this->getAllOptions($select);
|
||||
// Filter to items with title containing 'Test preview'.
|
||||
$options = array_filter($options, function(\SimpleXMLElement $item) {
|
||||
return strpos((string) $item[0], 'Child link') !== FALSE;
|
||||
});
|
||||
$this->assertEqual(1, count($options));
|
||||
|
||||
// Now add a new node with no menu.
|
||||
$this->drupalGet('node/add/page');
|
||||
$this->drupalPostForm(NULL, [
|
||||
'title[0][value]' => 'Node menu adding menu later test',
|
||||
'body[0][value]' => 'Going to add a menu link on edit',
|
||||
'menu[enabled]' => 0,
|
||||
], t('Save and publish'));
|
||||
$node = $this->drupalGetNodeByTitle('Node menu adding menu later test');
|
||||
// Now edit it and add a menu item.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
$this->drupalPostForm(NULL, [
|
||||
'title[0][value]' => 'Node menu adding menu later test',
|
||||
'body[0][value]' => 'This is a [node:menu-link:parent:url:path] token to the menu link parent',
|
||||
'menu[enabled]' => 1,
|
||||
'menu[title]' => 'Child link',
|
||||
'menu[menu_parent]' => 'main-menu:' . $parent_link->getPluginId(),
|
||||
], t('Save and keep published'));
|
||||
$node = $this->drupalGetNodeByTitle('Node menu adding menu later test', TRUE);
|
||||
$this->assertEqual('This is a /admin/config token to the menu link parent', $node->body->value);
|
||||
// And make sure the menu link exists with the right URI.
|
||||
$link = menu_ui_get_menu_link_defaults($node);
|
||||
$this->assertTrue(!empty($link['entity_id']));
|
||||
$query = \Drupal::entityQuery('menu_link_content')
|
||||
->condition('link.uri', 'entity:node/' . $node->id())
|
||||
->sort('id', 'ASC')
|
||||
->range(0, 1);
|
||||
$result = $query->execute();
|
||||
$this->assertTrue($result);
|
||||
|
||||
// Create a node with a menu link and create 2 menu links linking to this
|
||||
// node after. Verify that the menu link provided by the node has priority.
|
||||
$node_title = $this->randomMachineName();
|
||||
$edit = [
|
||||
'title[0][value]' => $node_title,
|
||||
'menu[enabled]' => 1,
|
||||
'menu[title]' => 'menu link provided by node',
|
||||
];
|
||||
$this->drupalPostForm('node/add/page', $edit, t('Save and publish'));
|
||||
$this->assertText('page ' . $node_title . ' has been created');
|
||||
$node = $this->drupalGetNodeByTitle($node_title);
|
||||
|
||||
$menu_ui_link1 = entity_create('menu_link_content', [
|
||||
'link' => ['uri' => 'entity:node/' . $node->id()],
|
||||
'title' => 'menu link 1 provided by menu ui',
|
||||
'menu_name' => 'main-menu',
|
||||
]);
|
||||
$menu_ui_link1->save();
|
||||
|
||||
$menu_ui_link2 = entity_create('menu_link_content', [
|
||||
'link' => ['uri' => 'entity:node/' . $node->id()],
|
||||
'title' => 'menu link 2 provided by menu ui',
|
||||
'menu_name' => 'main-menu',
|
||||
]);
|
||||
$menu_ui_link2->save();
|
||||
|
||||
$tokens = [
|
||||
'menu-link' => 'menu link provided by node',
|
||||
'menu-link:title' => 'menu link provided by node',
|
||||
];
|
||||
$this->assertTokens('node', ['node' => $node], $tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the module doesn't affect integrity of the menu, when
|
||||
* translating them and that menu links tokens are correct.
|
||||
*/
|
||||
function testMultilingualMenu() {
|
||||
// Place the menu block.
|
||||
$this->drupalPlaceBlock('system_menu_block:main');
|
||||
|
||||
// Add a second language.
|
||||
$language = ConfigurableLanguage::create([
|
||||
'id' => 'de',
|
||||
'label' => 'German',
|
||||
]);
|
||||
$language->save();
|
||||
|
||||
// Create the article content type.
|
||||
$node_type = NodeType::create([
|
||||
'type' => 'article',
|
||||
]);
|
||||
$node_type->save();
|
||||
|
||||
$permissions = array(
|
||||
'access administration pages',
|
||||
'administer content translation',
|
||||
'administer content types',
|
||||
'administer languages',
|
||||
'create content translations',
|
||||
'create article content',
|
||||
'edit any article content',
|
||||
'translate any entity',
|
||||
'administer menu',
|
||||
);
|
||||
$this->drupalLogin($this->drupalCreateUser($permissions));
|
||||
|
||||
// Enable translation for articles and menu links.
|
||||
$this->drupalGet('admin/config/regional/content-language');
|
||||
$edit = array(
|
||||
'entity_types[node]' => TRUE,
|
||||
'entity_types[menu_link_content]' => TRUE,
|
||||
'settings[node][article][translatable]' => TRUE,
|
||||
'settings[node][article][fields][title]' => TRUE,
|
||||
'settings[menu_link_content][menu_link_content][translatable]' => TRUE,
|
||||
);
|
||||
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
|
||||
$this->assertText('Settings successfully updated.');
|
||||
|
||||
// Create an english node with an english menu.
|
||||
$this->drupalGet('/node/add/article');
|
||||
$edit = [
|
||||
'title[0][value]' => 'English test node with menu',
|
||||
'menu[enabled]' => TRUE,
|
||||
'menu[title]' => 'English menu title',
|
||||
];
|
||||
$this->drupalPostForm('/node/add/article', $edit, t('Save'));
|
||||
$this->assertText('English test node with menu has been created.');
|
||||
|
||||
// Add a german translation.
|
||||
$this->drupalGet('node/1/translations');
|
||||
$this->clickLink('Add');
|
||||
$edit = [
|
||||
'title[0][value]' => 'German test node with menu',
|
||||
'menu[enabled]' => TRUE,
|
||||
'menu[title]' => 'German menu title',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save (this translation)'));
|
||||
$this->assertText('German test node with menu has been updated.');
|
||||
|
||||
// Verify that the menu links are correct.
|
||||
$this->drupalGet('node/1');
|
||||
$this->assertLink('English menu title');
|
||||
$this->drupalGet('de/node/1');
|
||||
$this->assertLink('German menu title');
|
||||
|
||||
// Verify that tokens are correct.
|
||||
$node = Node::load(1);
|
||||
$this->assertTokens('node', ['node' => $node], ['menu-link' => 'English menu title']);
|
||||
$this->assertTokens('node', ['node' => $node], [
|
||||
'menu-link' => 'German menu title',
|
||||
'menu-link:title' => 'German menu title',
|
||||
], ['langcode' => 'de']);
|
||||
|
||||
// Get the menu link and create a child menu link to assert parent and root
|
||||
// tokens.
|
||||
$url = $node->toUrl();
|
||||
/** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
|
||||
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
|
||||
$links = $menu_link_manager->loadLinksByRoute($url->getRouteName(), $url->getRouteParameters());
|
||||
$link = reset($links);
|
||||
|
||||
$base_options = [
|
||||
'provider' => 'menu_test',
|
||||
'menu_name' => 'menu_test',
|
||||
];
|
||||
$child_1 = $base_options + [
|
||||
'title' => 'child_1 title EN',
|
||||
'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1'],
|
||||
'parent' => $link->getPluginId(),
|
||||
'langcode' => 'en',
|
||||
];
|
||||
$child_1 = MenuLinkContent::create($child_1);
|
||||
$child_1->save();
|
||||
|
||||
// Add the german translation.
|
||||
$child_1->addTranslation('de', ['title' => 'child_1 title DE'] + $child_1->toArray());
|
||||
$child_1->save();
|
||||
|
||||
$this->assertTokens('menu-link', ['menu-link' => $child_1], [
|
||||
'title' => 'child_1 title EN',
|
||||
'parents' => 'English menu title',
|
||||
'root' => 'English menu title',
|
||||
]);
|
||||
$this->assertTokens('menu-link', ['menu-link' => $child_1], [
|
||||
'title' => 'child_1 title DE',
|
||||
'parents' => 'German menu title',
|
||||
'root' => 'German menu title',
|
||||
], ['langcode' => 'de']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests menu link parents token.
|
||||
*/
|
||||
public function testMenuLinkParentsToken() {
|
||||
// Create a menu with a simple link hierarchy :
|
||||
// - parent
|
||||
// - child-1
|
||||
// - child-1-1
|
||||
Menu::create(array(
|
||||
'id' => 'menu_test',
|
||||
'label' => 'Test menu',
|
||||
))->save();
|
||||
$base_options = [
|
||||
'provider' => 'menu_test',
|
||||
'menu_name' => 'menu_test',
|
||||
];
|
||||
$parent = $base_options + [
|
||||
'title' => 'parent title',
|
||||
'link' => ['uri' => 'internal:/menu-test/hierarchy/parent'],
|
||||
];
|
||||
$parent = MenuLinkContent::create($parent);
|
||||
$parent->save();
|
||||
$child_1 = $base_options + [
|
||||
'title' => 'child_1 title',
|
||||
'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1'],
|
||||
'parent' => $parent->getPluginId(),
|
||||
];
|
||||
$child_1 = MenuLinkContent::create($child_1);
|
||||
$child_1->save();
|
||||
$child_1_1 = $base_options + [
|
||||
'title' => 'child_1_1 title',
|
||||
'link' => ['uri' => 'internal:/menu-test/hierarchy/parent/child_1/child_1_1'],
|
||||
'parent' => $child_1->getPluginId(),
|
||||
];
|
||||
$child_1_1 = MenuLinkContent::create($child_1_1);
|
||||
$child_1_1->save();
|
||||
|
||||
$this->assertTokens('menu-link', ['menu-link' => $child_1_1], ['parents' => 'parent title, child_1 title']);
|
||||
|
||||
// Change the parent of child_1_1 to 'parent' at the entity level.
|
||||
$child_1_1->parent->value = $parent->getPluginId();
|
||||
$child_1_1->save();
|
||||
|
||||
$this->assertTokens('menu-link', ['menu-link' => $child_1_1], ['parents' => 'parent title']);
|
||||
|
||||
// Change the parent of child_1_1 to 'main', at the entity level.
|
||||
$child_1_1->parent->value = '';
|
||||
$child_1_1->save();
|
||||
|
||||
// The token shouldn't have been generated; the menu link has no parent.
|
||||
$this->assertNoTokens('menu-link', ['menu-link' => $child_1_1], ['parents']);
|
||||
}
|
||||
|
||||
}
|
||||
21
web/modules/contrib/token/src/Tests/TokenTestBase.php
Normal file
21
web/modules/contrib/token/src/Tests/TokenTestBase.php
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Helper test class with some added functions for testing.
|
||||
*/
|
||||
abstract class TokenTestBase extends WebTestBase {
|
||||
|
||||
use TokenTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('path', 'token', 'token_module_test');
|
||||
|
||||
}
|
||||
111
web/modules/contrib/token/src/Tests/TokenTestTrait.php
Normal file
111
web/modules/contrib/token/src/Tests/TokenTestTrait.php
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
|
||||
/**
|
||||
* Helper test trait with some added functions for testing.
|
||||
*/
|
||||
trait TokenTestTrait {
|
||||
|
||||
function assertToken($type, array $data, $token, $expected, array $options = array()) {
|
||||
return $this->assertTokens($type, $data, array($token => $expected), $options);
|
||||
}
|
||||
|
||||
function assertTokens($type, array $data, array $tokens, array $options = array()) {
|
||||
$input = $this->mapTokenNames($type, array_keys($tokens));
|
||||
$bubbleable_metadata = new BubbleableMetadata();
|
||||
$replacements = \Drupal::token()->generate($type, $input, $data, $options, $bubbleable_metadata);
|
||||
foreach ($tokens as $name => $expected) {
|
||||
$token = $input[$name];
|
||||
if (!isset($expected)) {
|
||||
$this->assertTrue(!isset($replacements[$token]), t("Token value for @token was not generated.", array('@type' => $type, '@token' => $token)));
|
||||
}
|
||||
elseif (!isset($replacements[$token])) {
|
||||
$this->fail(t("Token value for @token was not generated.", array('@type' => $type, '@token' => $token)));
|
||||
}
|
||||
elseif (!empty($options['regex'])) {
|
||||
$this->assertTrue(preg_match('/^' . $expected . '$/', $replacements[$token]), t("Token value for @token was '@actual', matching regular expression pattern '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $replacements[$token], '@expected' => $expected)));
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($replacements[$token], $expected, t("Token value for @token was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $replacements[$token], '@expected' => $expected)));
|
||||
}
|
||||
}
|
||||
|
||||
return $replacements;
|
||||
}
|
||||
|
||||
function mapTokenNames($type, array $tokens = array()) {
|
||||
$return = array();
|
||||
foreach ($tokens as $token) {
|
||||
$return[$token] = "[$type:$token]";
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function assertNoTokens($type, array $data, array $tokens, array $options = array()) {
|
||||
$input = $this->mapTokenNames($type, $tokens);
|
||||
$bubbleable_metadata = new BubbleableMetadata();
|
||||
$replacements = \Drupal::token()->generate($type, $input, $data, $options, $bubbleable_metadata);
|
||||
foreach ($tokens as $name) {
|
||||
$token = $input[$name];
|
||||
$this->assertTrue(!isset($replacements[$token]), t("Token value for @token was not generated.", array('@type' => $type, '@token' => $token)));
|
||||
}
|
||||
}
|
||||
|
||||
function saveAlias($source, $alias, $language = Language::LANGCODE_NOT_SPECIFIED) {
|
||||
$alias = array(
|
||||
'source' => $source,
|
||||
'alias' => $alias,
|
||||
'language' => $language,
|
||||
);
|
||||
\Drupal::service('path.alias_storage')->save($alias['source'], $alias['alias']);
|
||||
return $alias;
|
||||
}
|
||||
|
||||
function saveEntityAlias($entity_type, EntityInterface $entity, $alias, $language = Language::LANGCODE_NOT_SPECIFIED) {
|
||||
$uri = $entity->toUrl()->toArray();
|
||||
return $this->saveAlias($uri['path'], $alias, $language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a page request and test for token generation.
|
||||
*/
|
||||
function assertPageTokens($url, array $tokens, array $data = array(), array $options = array()) {
|
||||
if (empty($tokens)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
$token_page_tokens = array(
|
||||
'tokens' => $tokens,
|
||||
'data' => $data,
|
||||
'options' => $options,
|
||||
);
|
||||
\Drupal::state()->set('token_page_tokens', $token_page_tokens);
|
||||
|
||||
$options += array('url_options' => array());
|
||||
$this->drupalGet($url, $options['url_options']);
|
||||
$this->refreshVariables();
|
||||
$result = \Drupal::state()->get('token_page_tokens', array());
|
||||
|
||||
if (!isset($result['values']) || !is_array($result['values'])) {
|
||||
return $this->fail('Failed to generate tokens.');
|
||||
}
|
||||
|
||||
foreach ($tokens as $token => $expected) {
|
||||
if (!isset($expected)) {
|
||||
$this->assertTrue(!isset($result['values'][$token]) || $result['values'][$token] === $token, t("Token value for @token was not generated.", array('@token' => $token)));
|
||||
}
|
||||
elseif (!isset($result['values'][$token])) {
|
||||
$this->fail(t('Failed to generate token @token.', array('@token' => $token)));
|
||||
}
|
||||
else {
|
||||
$this->assertIdentical($result['values'][$token], (string) $expected, t("Token value for @token was '@actual', expected value '@expected'.", array('@token' => $token, '@actual' => $result['values'][$token], '@expected' => $expected)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
51
web/modules/contrib/token/src/Tests/TokenURLTest.php
Normal file
51
web/modules/contrib/token/src/Tests/TokenURLTest.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
* Tests url tokens.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenURLTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('node');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->saveAlias('/node/1', '/first-node');
|
||||
}
|
||||
|
||||
function testURLTokens() {
|
||||
$url = new Url('entity.node.canonical', array('node' => 1));
|
||||
$tokens = array(
|
||||
'absolute' => $url->setAbsolute()->toString(),
|
||||
'relative' => $url->setAbsolute(FALSE)->toString(),
|
||||
'path' => '/first-node',
|
||||
'brief' => preg_replace(array('!^https?://!', '!/$!'), '', $url->setAbsolute()->toString()),
|
||||
'args:value:0' => 'first-node',
|
||||
'args:value:1' => NULL,
|
||||
'args:value:N' => NULL,
|
||||
'unaliased' => $url->setAbsolute()->setOption('alias', TRUE)->toString(),
|
||||
'unaliased:relative' => $url->setAbsolute(FALSE)->setOption('alias', TRUE)->toString(),
|
||||
'unaliased:path' => '/node/1',
|
||||
'unaliased:brief' => preg_replace(array('!^https?://!', '!/$!'), '', $url->setAbsolute()->setOption('alias', TRUE)->toString()),
|
||||
'unaliased:args:value:0' => 'node',
|
||||
'unaliased:args:value:1' => '1',
|
||||
'unaliased:args:value:2' => NULL,
|
||||
// Deprecated tokens.
|
||||
'alias' => '/first-node',
|
||||
);
|
||||
$this->assertTokens('url', array('url' => new Url('entity.node.canonical', array('node' => 1))), $tokens);
|
||||
}
|
||||
}
|
||||
116
web/modules/contrib/token/src/Tests/TokenUserTest.php
Normal file
116
web/modules/contrib/token/src/Tests/TokenUserTest.php
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests;
|
||||
|
||||
use Drupal\Core\Session\AnonymousUserSession;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
|
||||
/**
|
||||
* Tests user tokens.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TokenUserTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* The user account.
|
||||
*
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account = NULL;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('token_user_picture');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->account = $this->drupalCreateUser(['administer users', 'administer account settings']);
|
||||
$this->drupalLogin($this->account);
|
||||
}
|
||||
|
||||
public function testUserTokens() {
|
||||
// Enable user pictures.
|
||||
\Drupal::state()->set('user_pictures', 1);
|
||||
\Drupal::state()->set('user_picture_file_size', '');
|
||||
|
||||
// Set up the pictures directory.
|
||||
$picture_path = file_default_scheme() . '://' . \Drupal::state()->get('user_picture_path', 'pictures');
|
||||
if (!file_prepare_directory($picture_path, FILE_CREATE_DIRECTORY)) {
|
||||
$this->fail('Could not create directory ' . $picture_path . '.');
|
||||
}
|
||||
|
||||
// Add a user picture to the account.
|
||||
$image = current($this->drupalGetTestFiles('image'));
|
||||
$edit = array('files[user_picture_0]' => drupal_realpath($image->uri));
|
||||
$this->drupalPostForm('user/' . $this->account->id() . '/edit', $edit, t('Save'));
|
||||
|
||||
$storage = \Drupal::entityTypeManager()->getStorage('user');
|
||||
|
||||
// Load actual user data from database.
|
||||
$storage->resetCache();
|
||||
$this->account = $storage->load($this->account->id());
|
||||
$this->assertTrue(!empty($this->account->user_picture->target_id), 'User picture uploaded.');
|
||||
|
||||
$picture = [
|
||||
'#theme' => 'user_picture',
|
||||
'#account' => $this->account,
|
||||
];
|
||||
/** @var \Drupal\Core\Render\RendererInterface $renderer */
|
||||
$renderer = \Drupal::service('renderer');
|
||||
$user_tokens = array(
|
||||
'picture' => $renderer->renderPlain($picture),
|
||||
'picture:fid' => $this->account->user_picture->target_id,
|
||||
'picture:size-raw' => 125,
|
||||
'ip-address' => NULL,
|
||||
'roles' => implode(', ', $this->account->getRoles()),
|
||||
);
|
||||
$this->assertTokens('user', array('user' => $this->account), $user_tokens);
|
||||
|
||||
// Remove the simpletest-created user role.
|
||||
$roles = $this->account->getRoles();
|
||||
$this->account->removeRole(end($roles));
|
||||
$this->account->save();
|
||||
|
||||
// Remove the user picture field and reload the user.
|
||||
FieldStorageConfig::loadByName('user', 'user_picture')->delete();
|
||||
$storage->resetCache();
|
||||
$this->account = $storage->load($this->account->id());
|
||||
|
||||
$user_tokens = array(
|
||||
'picture' => NULL,
|
||||
'picture:fid' => NULL,
|
||||
'ip-address' => NULL,
|
||||
'roles' => 'authenticated',
|
||||
'roles:keys' => (string) DRUPAL_AUTHENTICATED_RID,
|
||||
);
|
||||
$this->assertTokens('user', array('user' => $this->account), $user_tokens);
|
||||
|
||||
// The ip address token should work for the current user token type.
|
||||
$tokens = array(
|
||||
'ip-address' => \Drupal::request()->getClientIp(),
|
||||
);
|
||||
$this->assertTokens('current-user', array(), $tokens);
|
||||
|
||||
$anonymous = new AnonymousUserSession();
|
||||
$tokens = array(
|
||||
'roles' => 'anonymous',
|
||||
'roles:keys' => (string) DRUPAL_ANONYMOUS_RID,
|
||||
);
|
||||
$this->assertTokens('user', array('user' => $anonymous), $tokens);
|
||||
}
|
||||
|
||||
public function testUserAccountSettings() {
|
||||
$this->drupalGet('admin/config/people/accounts');
|
||||
$this->assertText('The list of available tokens that can be used in e-mails is provided below.');
|
||||
$this->assertLink('Browse available tokens.');
|
||||
$this->assertLinkByHref('token/tree');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests\Tree;
|
||||
|
||||
use Drupal\token\Tests\TokenTestBase;
|
||||
|
||||
/**
|
||||
* Test token autocomplete.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class AutocompleteTest extends TokenTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
/**
|
||||
* Tests autocomplete for node tokens.
|
||||
*/
|
||||
public function testNodeAutocomplete() {
|
||||
$url_prefix = "token/autocomplete/node/";
|
||||
|
||||
$url = $url_prefix . 'Title of [nod';
|
||||
$response = $this->drupalGetJSON($url);
|
||||
|
||||
$this->assertTrue(isset($response['[node:nid]']));
|
||||
$this->assertTrue(isset($response['[node:author]']));
|
||||
$this->assertTrue(isset($response['[node:url]']));
|
||||
$this->assertTrue(isset($response['[node:url:']));
|
||||
|
||||
$url = $url_prefix . 'Title of [node:url:';
|
||||
$response = $this->drupalGetJSON($url);
|
||||
|
||||
$this->assertTrue(isset($response['[node:url:path]']));
|
||||
$this->assertTrue(isset($response['[node:url:absolute]']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests autocomplete for user tokens.
|
||||
*/
|
||||
public function testUserAutocomplete() {
|
||||
$url_prefix = "token/autocomplete/user/";
|
||||
|
||||
$url = $url_prefix . 'Name of the [us';
|
||||
$response = $this->drupalGetJSON($url);
|
||||
|
||||
$this->assertTrue(isset($response['[user:uid]']));
|
||||
$this->assertTrue(isset($response['[user:original]']));
|
||||
$this->assertTrue(isset($response['[user:url]']));
|
||||
$this->assertTrue(isset($response['[user:url:']));
|
||||
|
||||
$url = $url_prefix . 'Title of [user:original:';
|
||||
$response = $this->drupalGetJSON($url);
|
||||
|
||||
$this->assertTrue(isset($response['[user:original:uid]']));
|
||||
}
|
||||
}
|
||||
69
web/modules/contrib/token/src/Tests/Tree/HelpPageTest.php
Normal file
69
web/modules/contrib/token/src/Tests/Tree/HelpPageTest.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests\Tree;
|
||||
|
||||
use Drupal\token\Tests\TokenTestBase;
|
||||
|
||||
/**
|
||||
* Tests token tree on help page.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class HelpPageTest extends TokenTestBase {
|
||||
|
||||
use TokenTreeTestTrait;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['help'];
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->account = $this->drupalCreateUser(['access administration pages']);
|
||||
$this->drupalLogin($this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the token browser on the token help page.
|
||||
*/
|
||||
public function testHelpPageTree() {
|
||||
$this->drupalGet('admin/help/token');
|
||||
$this->assertText('The list of the currently available tokens on this site are shown below.');
|
||||
|
||||
$this->assertTokenGroup('Current date');
|
||||
$this->assertTokenGroup('Site information');
|
||||
|
||||
$this->assertTokenInTree('[current-date:html_date]', 'current-date');
|
||||
$this->assertTokenInTree('[current-date:html_week]', 'current-date');
|
||||
$this->assertTokenInTree('[date:html_date]', 'date');
|
||||
$this->assertTokenInTree('[date:html_week]', 'date');
|
||||
|
||||
$this->assertTokenInTree('[current-user:account-name]', 'current-user');
|
||||
$this->assertTokenInTree('[user:account-name]', 'user');
|
||||
|
||||
$this->assertTokenInTree('[current-page:url:unaliased]', 'current-page--url');
|
||||
$this->assertTokenInTree('[current-page:url:unaliased:args]', 'current-page--url--unaliased');
|
||||
$this->assertTokenInTree('[user:original:account-name]', 'user--original');
|
||||
|
||||
// Assert some of the restricted tokens to ensure they are shown.
|
||||
$this->assertTokenInTree('[user:one-time-login-url]', 'user');
|
||||
$this->assertTokenInTree('[user:original:cancel-url]', 'user--original');
|
||||
|
||||
// The Array token is marked as nested, so it should not show up as a top
|
||||
// level token, only nested under another token. For instance, user:roles
|
||||
// is of type Array and tokens of type Array have 'nested' setting true.
|
||||
$this->assertTokenNotGroup('Array');
|
||||
$this->assertTokenNotGroup('user:roles');
|
||||
$this->assertTokenInTree('[user:roles]', 'user');
|
||||
}
|
||||
|
||||
}
|
||||
131
web/modules/contrib/token/src/Tests/Tree/TokenTreeTestTrait.php
Normal file
131
web/modules/contrib/token/src/Tests/Tree/TokenTreeTestTrait.php
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests\Tree;
|
||||
|
||||
/**
|
||||
* Helper trait to assert tokens in token tree browser.
|
||||
*/
|
||||
trait TokenTreeTestTrait {
|
||||
|
||||
/**
|
||||
* Get an array of token groups from the last retrieved page.
|
||||
*
|
||||
* @return array
|
||||
* Array of token group names.
|
||||
*/
|
||||
protected function getTokenGroups() {
|
||||
$groups = $this->xpath('//tr[contains(@class, "token-group")]/td[1]');
|
||||
return array_map(function ($item) {
|
||||
return (string) $item;
|
||||
}, $groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the specified token group is present in the token browser.
|
||||
*
|
||||
* @param string $token_group
|
||||
* The name of the token group.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output.
|
||||
*/
|
||||
protected function assertTokenGroup($token_group, $message = '', $group = 'Other') {
|
||||
$groups = $this->getTokenGroups();
|
||||
|
||||
if (!$message) {
|
||||
$message = "Token group $token_group found.";
|
||||
}
|
||||
|
||||
$this->assertTrue(in_array($token_group, $groups), $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the specified token group is not present in the token
|
||||
* browser.
|
||||
*
|
||||
* @param string $token_group
|
||||
* The name of the token group.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is not in, which is displayed in a
|
||||
* column in test output.
|
||||
*/
|
||||
protected function assertTokenNotGroup($token_group, $message = '', $group = 'Other') {
|
||||
$groups = $this->getTokenGroups();
|
||||
|
||||
if (!$message) {
|
||||
$message = "Token group $token_group not found.";
|
||||
}
|
||||
|
||||
$this->assertFalse(in_array($token_group, $groups), $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the specified token is present in the token browser.
|
||||
*
|
||||
* @param $token
|
||||
* The token name with the surrounding square brackets [].
|
||||
* @param string $parent
|
||||
* (optional) The parent CSS identifier of this token.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output.
|
||||
*/
|
||||
protected function assertTokenInTree($token, $parent = '', $message = '', $group = 'Other') {
|
||||
$xpath = $this->getXpathForTokenInTree($token, $parent);
|
||||
|
||||
if (!$message) {
|
||||
$message = "Token $token found.";
|
||||
}
|
||||
|
||||
$this->assertIdentical(1, count($this->xpath($xpath)), $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if the specified token is present in the token browser.
|
||||
*
|
||||
* @param $token
|
||||
* The token name with the surrounding square brackets [].
|
||||
* @param string $parent
|
||||
* (optional) The parent CSS identifier of this token.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is in, which is displayed in a column
|
||||
* in test output.
|
||||
*/
|
||||
protected function assertTokenNotInTree($token, $parent = '', $message = '', $group = 'Other') {
|
||||
$xpath = $this->getXpathForTokenInTree($token, $parent);
|
||||
|
||||
if (!$message) {
|
||||
$message = "Token $token not found.";
|
||||
}
|
||||
|
||||
$this->assertIdentical(0, count($this->xpath($xpath)), $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get xpath to check for token in tree.
|
||||
*
|
||||
* @param $token
|
||||
* The token name with the surrounding square brackets [].
|
||||
* @param string $parent
|
||||
* (optional) The parent CSS identifier of this token.
|
||||
*
|
||||
* @return string
|
||||
* The xpath to check for the token and parent.
|
||||
*/
|
||||
protected function getXpathForTokenInTree($token, $parent = '') {
|
||||
$xpath = "//tr";
|
||||
if ($parent) {
|
||||
$xpath .= '[@data-tt-parent-id="token-' . $parent . '"]';
|
||||
}
|
||||
$xpath .= '/td[contains(@class, "token-key") and text() = "' . $token . '"]';
|
||||
return $xpath;
|
||||
}
|
||||
}
|
||||
148
web/modules/contrib/token/src/Tests/Tree/TreeTest.php
Normal file
148
web/modules/contrib/token/src/Tests/Tree/TreeTest.php
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token\Tests\Tree;
|
||||
|
||||
use Drupal\Component\Serialization\Json;
|
||||
use Drupal\token\Tests\TokenTestBase;
|
||||
|
||||
/**
|
||||
* Tests token tree page.
|
||||
*
|
||||
* @group token
|
||||
*/
|
||||
class TreeTest extends TokenTestBase {
|
||||
|
||||
use TokenTreeTestTrait;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Session\AccountInterface
|
||||
*/
|
||||
protected $account;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['node'];
|
||||
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->account = $this->drupalCreateUser(['administer account settings']);
|
||||
$this->drupalLogin($this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various tokens that are possible on the site.
|
||||
*/
|
||||
public function testAllTokens() {
|
||||
$this->drupalGet($this->getTokenTreeUrl(['token_types' => 'all']));
|
||||
|
||||
$this->assertTokenGroup('Current date');
|
||||
$this->assertTokenGroup('Site information');
|
||||
|
||||
$this->assertTokenInTree('[current-date:html_date]', 'current-date');
|
||||
$this->assertTokenInTree('[current-date:html_week]', 'current-date');
|
||||
$this->assertTokenInTree('[date:html_date]', 'date');
|
||||
$this->assertTokenInTree('[date:html_week]', 'date');
|
||||
|
||||
$this->assertTokenInTree('[current-user:account-name]', 'current-user');
|
||||
$this->assertTokenInTree('[user:account-name]', 'user');
|
||||
|
||||
$this->assertTokenInTree('[current-page:url:unaliased]', 'current-page--url');
|
||||
$this->assertTokenInTree('[current-page:url:unaliased:args]', 'current-page--url--unaliased');
|
||||
$this->assertTokenInTree('[user:original:account-name]', 'user--original');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test various tokens that are possible on the site.
|
||||
*/
|
||||
public function testGlobalTokens() {
|
||||
$this->drupalGet($this->getTokenTreeUrl());
|
||||
|
||||
$this->assertTokenGroup('Current date');
|
||||
$this->assertTokenGroup('Site information');
|
||||
|
||||
// Assert that non-global tokens are not listed.
|
||||
$this->assertTokenNotInTree('[user:account-name]', 'user');
|
||||
$this->assertTokenNotInTree('[user:original:account-name]', 'user--original');
|
||||
|
||||
// Assert some of the global tokens, just to be sure.
|
||||
$this->assertTokenInTree('[current-date:html_date]', 'current-date');
|
||||
$this->assertTokenInTree('[current-date:html_week]', 'current-date');
|
||||
|
||||
$this->assertTokenInTree('[current-user:account-name]', 'current-user');
|
||||
|
||||
$this->assertTokenInTree('[current-page:url:unaliased]', 'current-page--url');
|
||||
$this->assertTokenInTree('[current-page:url:unaliased:args]', 'current-page--url--unaliased');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the token browser displays the user tokens.
|
||||
*/
|
||||
public function testUserTokens() {
|
||||
$this->drupalGet($this->getTokenTreeUrl(['token_types' => ['user']]));
|
||||
|
||||
$this->assertTokenGroup('Users');
|
||||
|
||||
$this->assertTokenInTree('[user:account-name]', 'user');
|
||||
$this->assertTokenInTree('[user:original:account-name]', 'user--original');
|
||||
|
||||
// Assert some of the restricted tokens to ensure they are not shown.
|
||||
$this->assertTokenNotInTree('[user:one-time-login-url]', 'user');
|
||||
$this->assertTokenNotInTree('[user:original:cancel-url]', 'user--original');
|
||||
|
||||
// Request with show_restricted set to TRUE to show restricted tokens and
|
||||
// check for them.
|
||||
$this->drupalGet($this->getTokenTreeUrl(['token_types' => ['user'], 'show_restricted' => TRUE]));
|
||||
$this->assertEqual('MISS', $this->drupalGetHeader('x-drupal-dynamic-cache'), 'Cache was not hit');
|
||||
$this->assertTokenInTree('[user:one-time-login-url]', 'user');
|
||||
$this->assertTokenInTree('[user:original:cancel-url]', 'user--original');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the token browser displays the node tokens.
|
||||
*/
|
||||
public function testNodeTokens() {
|
||||
$this->drupalGet($this->getTokenTreeUrl(['token_types' => ['node']]));
|
||||
|
||||
$this->assertTokenGroup('Nodes');
|
||||
|
||||
$this->assertTokenInTree('[node:body]', 'node');
|
||||
$this->assertTokenInTree('[node:author:original:account-name]', 'node--author--original');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the token tree based on the specified options.
|
||||
*
|
||||
* The token tree route's URL requires CSRF and cannot be generated in the
|
||||
* test code. The CSRF token generated using the test runner's session is
|
||||
* different from the session inside the test environment. This is why the
|
||||
* link has to be generated inside the environment.
|
||||
*
|
||||
* This function calls a page in token_module_test module which generates the
|
||||
* link and the token. This then replaces the options query parameter with the
|
||||
* specified options.
|
||||
*
|
||||
* The page also uses a title callback to set title to a render array, which
|
||||
* allows us to test if [current-page:title] works properly.
|
||||
*
|
||||
* @param array $options
|
||||
* The options for the token tree browser.
|
||||
*
|
||||
* @return string
|
||||
* The complete URL of the token tree browser with the CSRF token.
|
||||
*/
|
||||
protected function getTokenTreeUrl($options = []) {
|
||||
$this->drupalGet('token_module_test/browse');
|
||||
$this->assertTitle('Available Tokens | Drupal');
|
||||
$links = $this->xpath('//a[contains(@href, :href)]/@href', array(':href' => 'token/tree'));
|
||||
$link = $this->getAbsoluteUrl((string) current($links));
|
||||
if (!empty($options)) {
|
||||
$options = Json::encode($options);
|
||||
$link = str_replace('options=%5B%5D', 'options=' . urlencode($options), $link);
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
}
|
||||
213
web/modules/contrib/token/src/Token.php
Normal file
213
web/modules/contrib/token/src/Token.php
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Utility\Token as TokenBase;
|
||||
|
||||
/**
|
||||
* Service to retrieve token information.
|
||||
*
|
||||
* This service replaces the core's token service and provides the same
|
||||
* functionality by extending it. It also provides additional functionality
|
||||
* commonly required by the additional support provided by token module and
|
||||
* other modules.
|
||||
*/
|
||||
class Token extends TokenBase implements TokenInterface {
|
||||
|
||||
/**
|
||||
* Token definitions.
|
||||
*
|
||||
* @var array[]|null
|
||||
* An array of token definitions, or NULL when the definitions are not set.
|
||||
*
|
||||
* @see self::resetInfo()
|
||||
*/
|
||||
protected $globalTokenTypes;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInfo() {
|
||||
if (empty($this->tokenInfo)) {
|
||||
$cache_id = 'token_info_sorted:' . $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
|
||||
$cache = $this->cache->get($cache_id);
|
||||
if ($cache) {
|
||||
$this->tokenInfo = $cache->data;
|
||||
}
|
||||
else {
|
||||
$token_info = $this->moduleHandler->invokeAll('token_info');
|
||||
$this->moduleHandler->alter('token_info', $token_info);
|
||||
|
||||
foreach (array_keys($token_info['types']) as $type_key) {
|
||||
if (isset($token_info['types'][$type_key]['type'])) {
|
||||
$base_type = $token_info['types'][$type_key]['type'];
|
||||
// If this token type extends another token type, then merge in
|
||||
// the base token type's tokens.
|
||||
if (isset($token_info['tokens'][$base_type])) {
|
||||
$token_info['tokens'] += [$type_key => []];
|
||||
$token_info['tokens'][$type_key] += $token_info['tokens'][$base_type];
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Add a 'type' value to each token type information.
|
||||
$token_info['types'][$type_key]['type'] = $type_key;
|
||||
}
|
||||
}
|
||||
|
||||
// Pre-sort tokens.
|
||||
$by_name = $this->prepareMultisort($token_info['types']);
|
||||
array_multisort($by_name, SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $token_info['types']);
|
||||
foreach (array_keys($token_info['tokens']) as $type) {
|
||||
$by_name = $this->prepareMultisort($token_info['tokens'][$type]);
|
||||
array_multisort($by_name, SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $token_info['tokens'][$type]);
|
||||
}
|
||||
|
||||
$this->tokenInfo = $token_info;
|
||||
$this->cache->set($cache_id, $this->tokenInfo, CacheBackendInterface::CACHE_PERMANENT, array(
|
||||
static::TOKEN_INFO_CACHE_TAG,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->tokenInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts data from the token data for use in array_multisort().
|
||||
*
|
||||
* @param array $token_info
|
||||
* List of tokens or token types, each element must have a name key.
|
||||
*
|
||||
* @return string[]
|
||||
* List of the names keyed by the token key.
|
||||
*/
|
||||
protected function prepareMultisort($token_info) {
|
||||
$by_name = [];
|
||||
foreach ($token_info as $key => $token_info_element) {
|
||||
$by_name[$key] = $token_info_element['name'];
|
||||
}
|
||||
return $by_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTokenInfo($token_type, $token) {
|
||||
if (empty($this->tokenInfo)) {
|
||||
$this->getInfo();
|
||||
}
|
||||
|
||||
return isset($this->tokenInfo['tokens'][$token_type][$token]) ? $this->tokenInfo['tokens'][$token_type][$token] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTypeInfo($token_type) {
|
||||
if (empty($this->tokenInfo)) {
|
||||
$this->getInfo();
|
||||
}
|
||||
|
||||
return isset($this->tokenInfo['types'][$token_type]) ? $this->tokenInfo['types'][$token_type] : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getGlobalTokenTypes() {
|
||||
if (empty($this->globalTokenTypes)) {
|
||||
$token_info = $this->getInfo();
|
||||
foreach ($token_info['types'] as $type => $type_info) {
|
||||
// If the token types has not specified that 'needs-data' => TRUE, then
|
||||
// it is a global token type that will always be replaced in any context.
|
||||
if (empty($type_info['needs-data'])) {
|
||||
$this->globalTokenTypes[] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->globalTokenTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getInvalidTokens($type, $tokens) {
|
||||
$token_info = $this->getInfo();
|
||||
$invalid_tokens = array();
|
||||
|
||||
foreach ($tokens as $token => $full_token) {
|
||||
if (isset($token_info['tokens'][$type][$token])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Split token up if it has chains.
|
||||
$parts = explode(':', $token, 2);
|
||||
|
||||
if (!isset($token_info['tokens'][$type][$parts[0]])) {
|
||||
// This is an invalid token (not defined).
|
||||
$invalid_tokens[] = $full_token;
|
||||
}
|
||||
elseif (count($parts) == 2) {
|
||||
$sub_token_info = $token_info['tokens'][$type][$parts[0]];
|
||||
if (!empty($sub_token_info['dynamic'])) {
|
||||
// If this token has been flagged as a dynamic token, skip it.
|
||||
continue;
|
||||
}
|
||||
elseif (empty($sub_token_info['type'])) {
|
||||
// If the token has chains, but does not support it, it is invalid.
|
||||
$invalid_tokens[] = $full_token;
|
||||
}
|
||||
else {
|
||||
// Recursively check the chained tokens.
|
||||
$sub_tokens = $this->findWithPrefix(array($token => $full_token), $parts[0]);
|
||||
$invalid_tokens = array_merge($invalid_tokens, $this->getInvalidTokens($sub_token_info['type'], $sub_tokens));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $invalid_tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getInvalidTokensByContext($value, array $valid_types = []) {
|
||||
if (in_array('all', $valid_types)) {
|
||||
$info = $this->getInfo();
|
||||
$valid_types = array_keys($info['types']);
|
||||
}
|
||||
else {
|
||||
// Add the token types that are always valid in global context.
|
||||
$valid_types = array_merge($valid_types, $this->getGlobalTokenTypes());
|
||||
}
|
||||
|
||||
$invalid_tokens = array();
|
||||
$value_tokens = is_string($value) ? $this->scan($value) : $value;
|
||||
|
||||
foreach ($value_tokens as $type => $tokens) {
|
||||
if (!in_array($type, $valid_types)) {
|
||||
// If the token type is not a valid context, its tokens are invalid.
|
||||
$invalid_tokens = array_merge($invalid_tokens, array_values($tokens));
|
||||
}
|
||||
else {
|
||||
// Check each individual token for validity.
|
||||
$invalid_tokens = array_merge($invalid_tokens, $this->getInvalidTokens($type, $tokens));
|
||||
}
|
||||
}
|
||||
|
||||
array_unique($invalid_tokens);
|
||||
return $invalid_tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resetInfo() {
|
||||
parent::resetInfo();
|
||||
$this->globalTokenTypes = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
82
web/modules/contrib/token/src/TokenEntityMapper.php
Normal file
82
web/modules/contrib/token/src/TokenEntityMapper.php
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||
|
||||
/**
|
||||
* Service to provide mappings between entity and token types.
|
||||
*
|
||||
* Why do we need this? Because when the token API was moved to core we did not
|
||||
* reuse the entity type as the base name for taxonomy terms and vocabulary
|
||||
* tokens.
|
||||
*/
|
||||
class TokenEntityMapper implements TokenEntityMapperInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Extension\ModuleHandlerInterface
|
||||
*/
|
||||
protected $moduleHandler;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $entityMappings;
|
||||
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, ModuleHandlerInterface $module_handler) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->moduleHandler = $module_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getEntityTypeMappings() {
|
||||
if (empty($this->entityMappings)) {
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type => $info) {
|
||||
$this->entityMappings[$entity_type] = $info->get('token_type') ?: $entity_type;
|
||||
}
|
||||
// Allow modules to alter the mapping array.
|
||||
$this->moduleHandler->alter('token_entity_mapping', $this->entityMappings);
|
||||
}
|
||||
|
||||
return $this->entityMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getEntityTypeForTokenType($token_type, $fallback = FALSE) {
|
||||
if (empty($this->entityMappings)) {
|
||||
$this->getEntityTypeMappings();
|
||||
}
|
||||
|
||||
$return = array_search($token_type, $this->entityMappings);
|
||||
return $return !== FALSE ? $return : ($fallback ? $token_type : FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getTokenTypeForEntityType($entity_type, $fallback = FALSE) {
|
||||
if (empty($this->entityMappings)) {
|
||||
$this->getEntityTypeMappings();
|
||||
}
|
||||
|
||||
return isset($this->entityMappings[$entity_type]) ? $this->entityMappings[$entity_type] : ($fallback ? $entity_type : FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resetInfo() {
|
||||
$this->entityMappings = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
53
web/modules/contrib/token/src/TokenEntityMapperInterface.php
Normal file
53
web/modules/contrib/token/src/TokenEntityMapperInterface.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
interface TokenEntityMapperInterface {
|
||||
|
||||
/**
|
||||
* Return an array of entity type to token type mappings.
|
||||
*
|
||||
* @return array
|
||||
* An array of mappings with entity type mapping to token type.
|
||||
*/
|
||||
public function getEntityTypeMappings();
|
||||
|
||||
/**
|
||||
* Return the entity type of a particular token type.
|
||||
*
|
||||
* @param string $token_type
|
||||
* The token type for which the mapping is returned.
|
||||
* @param bool $fallback
|
||||
* (optional) Defaults to FALSE. If true, the same $value is returned in
|
||||
* case the mapping was not found.
|
||||
*
|
||||
* @return string
|
||||
* The entity type of the token type specified.
|
||||
*
|
||||
* @see token_entity_info_alter()
|
||||
* @see http://drupal.org/node/737726
|
||||
*/
|
||||
function getEntityTypeForTokenType($token_type, $fallback = FALSE);
|
||||
|
||||
/**
|
||||
* Return the token type of a particular entity type.
|
||||
*
|
||||
* @param string $entity_type
|
||||
* The entity type for which the mapping is returned.
|
||||
* @param bool $fallback
|
||||
* (optional) Defaults to FALSE. If true, the same $value is returned in
|
||||
* case the mapping was not found.
|
||||
*
|
||||
* @return string
|
||||
* The token type of the entity type specified.
|
||||
*
|
||||
* @see token_entity_info_alter()
|
||||
* @see http://drupal.org/node/737726
|
||||
*/
|
||||
function getTokenTypeForEntityType($entity_type, $fallback = FALSE);
|
||||
|
||||
/**
|
||||
* Resets metadata describing token and entity mappings.
|
||||
*/
|
||||
public function resetInfo();
|
||||
}
|
||||
75
web/modules/contrib/token/src/TokenInterface.php
Normal file
75
web/modules/contrib/token/src/TokenInterface.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
interface TokenInterface {
|
||||
|
||||
/**
|
||||
* Returns metadata describing supported token types.
|
||||
*
|
||||
* @param $token_type
|
||||
* The token type for which the metadata is required.
|
||||
*
|
||||
* @return array[]
|
||||
* An array of token type information from hook_token_info() for the
|
||||
* specified token type.
|
||||
*
|
||||
* @see hook_token_info()
|
||||
* @see hook_token_info_alter()
|
||||
*/
|
||||
public function getTypeInfo($token_type);
|
||||
|
||||
/**
|
||||
* Returns metadata describing supported a token.
|
||||
*
|
||||
* @param $token_type
|
||||
* The token type for which the metadata is required.
|
||||
* @param $token
|
||||
* The token name for which the metadata is required.
|
||||
*
|
||||
* @return array[]
|
||||
* An array of information from hook_token_info() for the specified token.
|
||||
*
|
||||
* @see hook_token_info()
|
||||
* @see hook_token_info_alter()
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public function getTokenInfo($token_type, $token);
|
||||
|
||||
/**
|
||||
* Get a list of token types that can be used without any context (global).
|
||||
*
|
||||
* @return array[]
|
||||
* An array of global token types.
|
||||
*/
|
||||
public function getGlobalTokenTypes();
|
||||
|
||||
/**
|
||||
* Validate an array of tokens based on their token type.
|
||||
*
|
||||
* @param string $type
|
||||
* The type of tokens to validate (e.g. 'node', etc.)
|
||||
* @param string[] $tokens
|
||||
* A keyed array of tokens, and their original raw form in the source text.
|
||||
*
|
||||
* @return string[]
|
||||
* An array with the invalid tokens in their original raw forms.
|
||||
*/
|
||||
function getInvalidTokens($type, $tokens);
|
||||
|
||||
/**
|
||||
* Validate tokens in raw text based on possible contexts.
|
||||
*
|
||||
* @param string|string[] $value
|
||||
* A string with the raw text containing the raw tokens, or an array of
|
||||
* tokens from token_scan().
|
||||
* @param string[] $valid_types
|
||||
* An array of token types that will be used when token replacement is
|
||||
* performed.
|
||||
*
|
||||
* @return string[]
|
||||
* An array with the invalid tokens in their original raw forms.
|
||||
*/
|
||||
public function getInvalidTokensByContext($value, array $valid_types = []);
|
||||
}
|
||||
20
web/modules/contrib/token/src/TokenServiceProvider.php
Normal file
20
web/modules/contrib/token/src/TokenServiceProvider.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ServiceProviderBase;
|
||||
|
||||
/**
|
||||
* Replace core's token service with our own.
|
||||
*/
|
||||
class TokenServiceProvider extends ServiceProviderBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function alter(ContainerBuilder $container) {
|
||||
$definition = $container->getDefinition('token');
|
||||
$definition->setClass('\Drupal\token\Token');
|
||||
}
|
||||
}
|
||||
267
web/modules/contrib/token/src/TreeBuilder.php
Normal file
267
web/modules/contrib/token/src/TreeBuilder.php
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheBackendInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\Render\BubbleableMetadata;
|
||||
|
||||
class TreeBuilder implements TreeBuilderInterface {
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\Token
|
||||
*/
|
||||
protected $tokenService;
|
||||
|
||||
/**
|
||||
* @var \Drupal\token\TokenEntityMapperInterface
|
||||
*/
|
||||
protected $entityMapper;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Language\LanguageManagerInterface
|
||||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Cache\CacheBackendInterface
|
||||
*/
|
||||
protected $cacheBackend;
|
||||
|
||||
/**
|
||||
* Cache already built trees.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $builtTrees;
|
||||
|
||||
public function __construct(TokenInterface $token_service, TokenEntityMapperInterface $entity_mapper, CacheBackendInterface $cache_backend, LanguageManagerInterface $language_manager) {
|
||||
$this->tokenService = $token_service;
|
||||
$this->entityMapper = $entity_mapper;
|
||||
$this->cacheBackend = $cache_backend;
|
||||
$this->languageManager = $language_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildRenderable(array $token_types, array $options = []) {
|
||||
// Set default options.
|
||||
$options += [
|
||||
'global_types' => TRUE,
|
||||
'click_insert' => TRUE,
|
||||
'show_restricted' => FALSE,
|
||||
'show_nested' => FALSE,
|
||||
'recursion_limit' => 3,
|
||||
];
|
||||
|
||||
$info = $this->tokenService->getInfo();
|
||||
if ($options['global_types']) {
|
||||
$token_types = array_merge($token_types, $this->tokenService->getGlobalTokenTypes());
|
||||
}
|
||||
|
||||
$element = array(
|
||||
/*'#cache' => array(
|
||||
'cid' => 'tree-rendered:' . hash('sha256', serialize(array('token_types' => $token_types, 'global_types' => NULL) + $variables)),
|
||||
'tags' => array(Token::TOKEN_INFO_CACHE_TAG),
|
||||
),*/
|
||||
);
|
||||
|
||||
// @todo Find a way to use the render cache for this.
|
||||
/*if ($cached_output = token_render_cache_get($element)) {
|
||||
return $cached_output;
|
||||
}*/
|
||||
|
||||
$tree_options = [
|
||||
'flat' => TRUE,
|
||||
'restricted' => $options['show_restricted'],
|
||||
'nested' => $options['show_nested'],
|
||||
'depth' => $options['recursion_limit'],
|
||||
];
|
||||
|
||||
$token_tree = [];
|
||||
foreach ($info['types'] as $type => $type_info) {
|
||||
if (!in_array($type, $token_types)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$token_tree[$type] = $type_info;
|
||||
$token_tree[$type]['tokens'] = $this->buildTree($type, $tree_options);
|
||||
}
|
||||
|
||||
$element += [
|
||||
'#type' => 'token_tree_table',
|
||||
'#token_tree' => $token_tree,
|
||||
'#show_restricted' => $options['show_restricted'],
|
||||
'#show_nested' => $options['show_nested'],
|
||||
'#click_insert' => $options['click_insert'],
|
||||
'#columns' => ['name', 'token', 'description'],
|
||||
'#empty' => t('No tokens available'),
|
||||
];
|
||||
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildAllRenderable(array $options = []) {
|
||||
$info = $this->tokenService->getInfo();
|
||||
$token_types = array_keys($info['types']);
|
||||
|
||||
// Disable merging in global types as we will be adding in all token types
|
||||
// explicitly. There is no difference in leaving this set to TRUE except for
|
||||
// an additional method call which is unnecessary.
|
||||
$options['global_types'] = FALSE;
|
||||
return $this->buildRenderable($token_types, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildTree($token_type, array $options = []) {
|
||||
$options += [
|
||||
'restricted' => FALSE,
|
||||
'depth' => 4,
|
||||
'data' => [],
|
||||
'values' => FALSE,
|
||||
'flat' => FALSE,
|
||||
];
|
||||
|
||||
// Do not allow past the maximum token information depth.
|
||||
$options['depth'] = min($options['depth'], static::MAX_DEPTH);
|
||||
|
||||
// If $token_type is an entity, make sure we are using the actual token type.
|
||||
if ($entity_token_type = $this->entityMapper->getTokenTypeForEntityType($token_type)) {
|
||||
$token_type = $entity_token_type;
|
||||
}
|
||||
|
||||
$langcode = $this->languageManager->getCurrentLanguage()->getId();
|
||||
$tree_cid = "token_tree:{$token_type}:{$langcode}:{$options['depth']}";
|
||||
|
||||
// If we do not have this base tree in the static cache, check the cache
|
||||
// otherwise generate and store it in the cache.
|
||||
if (!isset($this->builtTrees[$tree_cid])) {
|
||||
if ($cache = $this->cacheBackend->get($tree_cid)) {
|
||||
$this->builtTrees[$tree_cid] = $cache->data;
|
||||
}
|
||||
else {
|
||||
$options['parents'] = [];
|
||||
$this->builtTrees[$tree_cid] = $this->getTokenData($token_type, $options);
|
||||
$this->cacheBackend->set($tree_cid, $this->builtTrees[$tree_cid], Cache::PERMANENT, [Token::TOKEN_INFO_CACHE_TAG]);
|
||||
}
|
||||
}
|
||||
|
||||
$tree = $this->builtTrees[$tree_cid];
|
||||
|
||||
// If the user has requested a flat tree, convert it.
|
||||
if (!empty($options['flat'])) {
|
||||
$tree = $this->flattenTree($tree);
|
||||
}
|
||||
|
||||
// Fill in token values.
|
||||
if (!empty($options['values'])) {
|
||||
$token_values = [];
|
||||
foreach ($tree as $token => $token_info) {
|
||||
if (!empty($token_info['dynamic']) || !empty($token_info['restricted'])) {
|
||||
continue;
|
||||
}
|
||||
elseif (!isset($token_info['value'])) {
|
||||
$token_values[$token_info['token']] = $token;
|
||||
}
|
||||
}
|
||||
if (!empty($token_values)) {
|
||||
$token_values = $this->tokenService->generate($token_type, $token_values, $options['data'], [], new BubbleableMetadata());
|
||||
foreach ($token_values as $token => $replacement) {
|
||||
$tree[$token]['value'] = $replacement;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function flattenTree(array $tree) {
|
||||
$result = [];
|
||||
foreach ($tree as $token => $token_info) {
|
||||
$result[$token] = $token_info;
|
||||
if (isset($token_info['children']) && is_array($token_info['children'])) {
|
||||
$result += $this->flattenTree($token_info['children']);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a token tree.
|
||||
*
|
||||
* @param string $token_type
|
||||
* The token type.
|
||||
* @param array $options
|
||||
* An associative array of additional options. See documentation for
|
||||
* TreeBuilderInterface::buildTree() for more information.
|
||||
*
|
||||
* @return array
|
||||
* The token data for the specified $token_type.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
protected function getTokenData($token_type, array $options) {
|
||||
$options += [
|
||||
'parents' => [],
|
||||
];
|
||||
|
||||
$info = $this->tokenService->getInfo();
|
||||
if ($options['depth'] <= 0 || !isset($info['types'][$token_type]) || !isset($info['tokens'][$token_type])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$tree = [];
|
||||
foreach ($info['tokens'][$token_type] as $token => $token_info) {
|
||||
// Build the raw token string.
|
||||
$token_parents = $options['parents'];
|
||||
if (empty($token_parents)) {
|
||||
// If the parents array is currently empty, assume the token type is its
|
||||
// parent.
|
||||
$token_parents[] = $token_type;
|
||||
}
|
||||
elseif (in_array($token, array_slice($token_parents, 1), TRUE)) {
|
||||
// Prevent duplicate recursive tokens. For example, this will prevent
|
||||
// the tree from generating the following tokens or deeper:
|
||||
// [comment:parent:parent]
|
||||
// [comment:parent:root:parent]
|
||||
continue;
|
||||
}
|
||||
|
||||
$token_parents[] = $token;
|
||||
if (!empty($token_info['dynamic'])) {
|
||||
$token_parents[] = '?';
|
||||
}
|
||||
$raw_token = '[' . implode(':', $token_parents) . ']';
|
||||
$tree[$raw_token] = $token_info;
|
||||
$tree[$raw_token]['raw token'] = $raw_token;
|
||||
|
||||
// Add the token's real name (leave out the base token type).
|
||||
$tree[$raw_token]['token'] = implode(':', array_slice($token_parents, 1));
|
||||
|
||||
// Add the token's parent as its raw token value.
|
||||
if (!empty($options['parents'])) {
|
||||
$tree[$raw_token]['parent'] = '[' . implode(':', $options['parents']) . ']';
|
||||
}
|
||||
|
||||
// Fetch the child tokens.
|
||||
if (!empty($token_info['type'])) {
|
||||
$child_options = $options;
|
||||
$child_options['depth']--;
|
||||
$child_options['parents'] = $token_parents;
|
||||
$tree[$raw_token]['children'] = $this->getTokenData($token_info['type'], $child_options);
|
||||
}
|
||||
}
|
||||
|
||||
return $tree;
|
||||
}
|
||||
}
|
||||
79
web/modules/contrib/token/src/TreeBuilderInterface.php
Normal file
79
web/modules/contrib/token/src/TreeBuilderInterface.php
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\token;
|
||||
|
||||
interface TreeBuilderInterface {
|
||||
|
||||
/**
|
||||
* The maximum depth for token tree recursion.
|
||||
*/
|
||||
const MAX_DEPTH = 9;
|
||||
|
||||
/**
|
||||
* Build a tree array of tokens used for themeing or information.
|
||||
*
|
||||
* @param string $token_type
|
||||
* The token type.
|
||||
* @param array $options
|
||||
* (optional) An associative array of additional options, with the following
|
||||
* elements:
|
||||
* - 'flat' (defaults to FALSE): Set to true to generate a flat list of
|
||||
* token information. Otherwise, child tokens will be inside the
|
||||
* 'children' parameter of a token.
|
||||
* - 'restricted' (defaults to FALSE): Set to true to how restricted tokens.
|
||||
* - 'depth' (defaults to 4): Maximum number of token levels to recurse.
|
||||
*
|
||||
* @return array
|
||||
* The token information constructed in a tree or flat list form depending
|
||||
* on $options['flat'].
|
||||
*/
|
||||
public function buildTree($token_type, array $options = []);
|
||||
|
||||
/**
|
||||
* Flatten a token tree.
|
||||
*
|
||||
* @param array $tree
|
||||
* The tree array as returned by TreeBuilderInterface::buildTree().
|
||||
*
|
||||
* @return array
|
||||
* The flattened version of the tree.
|
||||
*/
|
||||
public function flattenTree(array $tree);
|
||||
|
||||
/**
|
||||
* Build a render array with token tree built as per specified options.
|
||||
*
|
||||
* @param array $token_types
|
||||
* An array containing token types that should be shown in the tree.
|
||||
* @param array $options
|
||||
* (optional) An associative array to control which tokens are shown and
|
||||
* how. The properties available are:
|
||||
* - 'global_types' (defaults to TRUE): Show all global token types along
|
||||
* with the specified types.
|
||||
* - 'click_insert' (defaults to TRUE): Include classes and caption to show
|
||||
* allow inserting tokens in fields by clicking on them.
|
||||
* - 'show_restricted' (defaults to FALSE): Show restricted tokens in the
|
||||
* tree.
|
||||
* - 'show_nested' (defaults to FALSE): If this token is nested and should
|
||||
* therefor not show on the token browser as a top level token.
|
||||
* - 'recursion_limit' (defaults to 3): Only show tokens up to the specified
|
||||
* depth.
|
||||
*
|
||||
* @return array
|
||||
* Render array for the token tree.
|
||||
*/
|
||||
public function buildRenderable(array $token_types, array $options = []);
|
||||
|
||||
/**
|
||||
* Build a render array with token tree containing all possible tokens.
|
||||
*
|
||||
* @param array $options
|
||||
* (optional) An associative array to control which tokens are shown and
|
||||
* how. The properties available are: See
|
||||
* \Drupal\token\TreeBuilderInterface::buildRenderable() for details.
|
||||
*
|
||||
* @return array
|
||||
* Render array for the token tree.
|
||||
*/
|
||||
public function buildAllRenderable(array $options = []);
|
||||
}
|
||||
Reference in a new issue