diff --git a/composer.json b/composer.json index 062599973e1002a1bcb75e0361590fcde920f761..545b7bc6d727a50cd38d87e57754e2bc2dfe97d7 100644 --- a/composer.json +++ b/composer.json @@ -165,7 +165,7 @@ "drupal/social_media_links": "^2.8", "drupal/superfish": "1.4", "drupal/svg_image": "1.15", - "drupal/token": "1.9", + "drupal/token": "1.11", "drupal/twig_tweak": "2.9", "drupal/twitter_block": "3.0-alpha1", "drupal/ultimate_cron": "^2.0@alpha", diff --git a/composer.lock b/composer.lock index c4e0a873cba92f1ff9464754d0e03c2401b16b46..012f7be0a77f37512160632d146f1705882b62d7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "03a5824d6fa8642d5beb1999818d391f", + "content-hash": "cf5892a08916c24fe3a7342690decd98", "packages": [ { "name": "alchemy/zippy", @@ -7305,26 +7305,26 @@ }, { "name": "drupal/token", - "version": "1.9.0", + "version": "1.11.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/token.git", - "reference": "8.x-1.9" + "reference": "8.x-1.11" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/token-8.x-1.9.zip", - "reference": "8.x-1.9", - "shasum": "a5d234382a1a0e4ba61d4c7a2fa10671ca656be4" + "url": "https://ftp.drupal.org/files/projects/token-8.x-1.11.zip", + "reference": "8.x-1.11", + "shasum": "da264b36d1f88eb0c74bf84e18e8789854f98400" }, "require": { - "drupal/core": "^8.8 || ^9" + "drupal/core": "^9.2 || ^10" }, "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.9", - "datestamp": "1608284866", + "version": "8.x-1.11", + "datestamp": "1659471813", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 6c7ddd963ef13679a00ff343f6e7629a40383a5c..786696c473d3706b3042791c6c9e007f157311c7 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -7576,27 +7576,27 @@ }, { "name": "drupal/token", - "version": "1.9.0", - "version_normalized": "1.9.0.0", + "version": "1.11.0", + "version_normalized": "1.11.0.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/token.git", - "reference": "8.x-1.9" + "reference": "8.x-1.11" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/token-8.x-1.9.zip", - "reference": "8.x-1.9", - "shasum": "a5d234382a1a0e4ba61d4c7a2fa10671ca656be4" + "url": "https://ftp.drupal.org/files/projects/token-8.x-1.11.zip", + "reference": "8.x-1.11", + "shasum": "da264b36d1f88eb0c74bf84e18e8789854f98400" }, "require": { - "drupal/core": "^8.8 || ^9" + "drupal/core": "^9.2 || ^10" }, "type": "drupal-module", "extra": { "drupal": { - "version": "8.x-1.9", - "datestamp": "1608284866", + "version": "8.x-1.11", + "datestamp": "1659471813", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 98f6596b91e438771c59bb80542fa4b81794eb48..7d3cf901d65a23ff833e400219e48800a7912f74 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'osu-asc-webservices/d8-upstream', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '980147862f8ed56447f54527d88a8e341a7ded83', + 'reference' => '864332360465433168f0fa3c5657b2dacd15b33c', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -1235,9 +1235,9 @@ 'dev_requirement' => false, ), 'drupal/token' => array( - 'pretty_version' => '1.9.0', - 'version' => '1.9.0.0', - 'reference' => '8.x-1.9', + 'pretty_version' => '1.11.0', + 'version' => '1.11.0.0', + 'reference' => '8.x-1.11', 'type' => 'drupal-module', 'install_path' => __DIR__ . '/../../web/modules/token', 'aliases' => array(), @@ -1594,7 +1594,7 @@ 'osu-asc-webservices/d8-upstream' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '980147862f8ed56447f54527d88a8e341a7ded83', + 'reference' => '864332360465433168f0fa3c5657b2dacd15b33c', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/web/modules/token/js/token.js b/web/modules/token/js/token.js index 3a41d6259a18efde7c4d706769b993e8192ed9b8..8dc6acfcd9cbd08d38bb6af3e7235e11be534346 100644 --- a/web/modules/token/js/token.js +++ b/web/modules/token/js/token.js @@ -5,9 +5,7 @@ Drupal.behaviors.tokenTree = { attach: function (context, settings) { - $('table.token-tree', context).once('token-tree').each(function () { - $(this).treetable({ expandable: true }); - }); + $(once('token-tree', 'table.token-tree', context)).treetable({ expandable: true}); } }; @@ -18,8 +16,8 @@ drupalSettings.tokenFocusedField = this; }); - $('.token-click-insert .token-key', context).once('token-click-insert').each(function () { - var newThis = $('<a href="javascript:void(0);" title="' + Drupal.t('Insert this token into your form') + '">' + $(this).html() + '</a>').click(function () { + once('token-click-insert', '.token-click-insert .token-key', context).forEach(function (token) { + var newThis = $('<a href="javascript:void(0);" title="' + Drupal.t('Insert this token into your form') + '">' + $(token).html() + '</a>').click(function () { var content = this.text; // Always work in normal text areas that currently have focus. @@ -58,7 +56,7 @@ return false; }); - $(this).html(newThis); + $(token).html(newThis); }); function insertAtCursor(editor, content) { diff --git a/web/modules/token/migrations/state/token.migrate_drupal.yml b/web/modules/token/migrations/state/token.migrate_drupal.yml new file mode 100644 index 0000000000000000000000000000000000000000..e0196c288aa55830f6eb8088a7c9a29b79bcf0c8 --- /dev/null +++ b/web/modules/token/migrations/state/token.migrate_drupal.yml @@ -0,0 +1,5 @@ +finished: + 6: + token: token + 7: + token: token diff --git a/web/modules/token/src/Controller/TokenAutocompleteController.php b/web/modules/token/src/Controller/TokenAutocompleteController.php deleted file mode 100644 index 979f832a48df8913524191c2f2af9560fd838886..0000000000000000000000000000000000000000 --- a/web/modules/token/src/Controller/TokenAutocompleteController.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php - -namespace Drupal\token\Controller; - -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 = []; - - if (!mb_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); - } - -} diff --git a/web/modules/token/src/Element/TokenTreeTable.php b/web/modules/token/src/Element/TokenTreeTable.php index 6de9c95d3c2e3d3a392133a980e21c1597ecedbb..cc607d5db39ff6be67fa6093981d7e04b9a06c28 100644 --- a/web/modules/token/src/Element/TokenTreeTable.php +++ b/web/modules/token/src/Element/TokenTreeTable.php @@ -81,10 +81,6 @@ public static function preRenderTokenTree($element) { } } - if (!empty($element['#rows'])) { - $element['#attached']['library'][] = 'token/jquery.treeTable'; - } - // Fill headers if one is not specified. if (empty($element['#header'])) { $column_map = [ diff --git a/web/modules/token/src/Routing/RouteSubscriber.php b/web/modules/token/src/Routing/RouteSubscriber.php index b856f43e6f851f8ea4c86bc8f93c9d2fc1070604..65a232b6f4a223f94f15f097ea2457a38286729b 100644 --- a/web/modules/token/src/Routing/RouteSubscriber.php +++ b/web/modules/token/src/Routing/RouteSubscriber.php @@ -66,7 +66,7 @@ protected function alterRoutes(RouteCollection $collection) { /** * {@inheritdoc} */ - public static function getSubscribedEvents() { + public static function getSubscribedEvents(): array { $events = parent::getSubscribedEvents(); $events[RoutingEvents::ALTER] = array('onAlterRoutes', 100); return $events; diff --git a/web/modules/token/tests/modules/token_module_test/token_module_test.info.yml b/web/modules/token/tests/modules/token_module_test/token_module_test.info.yml index e58af02fce720ba1ca824352717485664677b4cd..6ceda27bc826e31d909e9c3d06c758a7b5e36506 100644 --- a/web/modules/token/tests/modules/token_module_test/token_module_test.info.yml +++ b/web/modules/token/tests/modules/token_module_test/token_module_test.info.yml @@ -2,10 +2,9 @@ type: module name: Token Module Test description: Testing module for token functionality. package: Testing -core_version_requirement: ^8.7.7 || ^9 hidden: TRUE -# Information added by Drupal.org packaging script on 2020-12-18 -version: '8.x-1.9' +# Information added by Drupal.org packaging script on 2022-08-02 +version: '8.x-1.11' project: 'token' -datestamp: 1608284868 +datestamp: 1659471815 diff --git a/web/modules/token/tests/modules/token_module_test/token_module_test.module b/web/modules/token/tests/modules/token_module_test/token_module_test.module index c022b6575c9efb5034e44452063d9400d692fd55..d76680c99d41b7009124cc772c5a1ab69375e18d 100644 --- a/web/modules/token/tests/modules/token_module_test/token_module_test.module +++ b/web/modules/token/tests/modules/token_module_test/token_module_test.module @@ -26,7 +26,7 @@ function token_module_test_page_attachments() { function token_module_test_node_presave(NodeInterface $node) { // Transform tokens in the body. // @see \Drupal\token\Tests\TokenMenuTest::testMenuTokens() - if ($node->hasField('body')) { + if ($node->hasField('body') && $node->get('body')->value) { $node->body->value = \Drupal::token() ->replace($node->body->value, ['node' => $node]); } diff --git a/web/modules/token/tests/modules/token_user_picture/token_user_picture.info.yml b/web/modules/token/tests/modules/token_user_picture/token_user_picture.info.yml index 601a0b85236e9e6e8337111e810468ed41bccab5..78b477996f5bf089006c67aadae8d569e737d99e 100644 --- a/web/modules/token/tests/modules/token_user_picture/token_user_picture.info.yml +++ b/web/modules/token/tests/modules/token_user_picture/token_user_picture.info.yml @@ -2,12 +2,11 @@ type: module name: Token User picture description: Testing module that provides user pictures field. package: Testing -core_version_requirement: ^8.7.7 || ^9 hidden: TRUE dependencies: - drupal:image -# Information added by Drupal.org packaging script on 2020-12-18 -version: '8.x-1.9' +# Information added by Drupal.org packaging script on 2022-08-02 +version: '8.x-1.11' project: 'token' -datestamp: 1608284868 +datestamp: 1659471815 diff --git a/web/modules/token/tests/src/Functional/TokenBlockTest.php b/web/modules/token/tests/src/Functional/TokenBlockTest.php index 4833df2ff3c0d0c089d2120bfd325a491d6c48f3..1fa9610b02a3c3e281426d44fd5919cfd7eb8077 100644 --- a/web/modules/token/tests/src/Functional/TokenBlockTest.php +++ b/web/modules/token/tests/src/Functional/TokenBlockTest.php @@ -13,16 +13,14 @@ class TokenBlockTest extends TokenTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['block', 'node', 'views', 'block_content']; + protected static $modules = ['block', 'node', 'views', 'block_content']; /** * {@inheritdoc} */ - public function setUp($modules = []) { + public function setUp(): void { parent::setUp(); $this->admin_user = $this->drupalCreateUser(['access content', 'administer blocks']); $this->drupalLogin($this->admin_user); @@ -52,10 +50,10 @@ public function testBlockTitleTokens() { // Ensure that the link to available tokens is present and correctly // positioned. $this->assertSession()->linkExists('Browse available tokens.'); - $this->assertText('This field supports tokens. Browse available tokens.'); - $this->drupalPostForm(NULL, [], 'Save block'); + $this->assertSession()->pageTextContains('This field supports tokens. Browse available tokens.'); + $this->submitForm([], 'Save block'); // Ensure token validation is working on the block. - $this->assertText('Title is using the following invalid tokens: [user:name].'); + $this->assertSession()->pageTextContains('Title is using the following invalid tokens: [user:name].'); // Create the block for real now with a valid title. $settings = $block->get('settings'); diff --git a/web/modules/token/tests/src/Functional/TokenCurrentPageTest.php b/web/modules/token/tests/src/Functional/TokenCurrentPageTest.php index d3d5cebf40a16883db6164d8a806cad7b94c048b..f5170147b731b97c662d4f5f40304343d51737ea 100644 --- a/web/modules/token/tests/src/Functional/TokenCurrentPageTest.php +++ b/web/modules/token/tests/src/Functional/TokenCurrentPageTest.php @@ -12,11 +12,9 @@ class TokenCurrentPageTest extends TokenTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node']; + protected static $modules = ['node']; function testCurrentPageTokens() { // Cache clear is necessary because the frontpage was already cached by an diff --git a/web/modules/token/tests/src/Functional/TokenFieldUiTest.php b/web/modules/token/tests/src/Functional/TokenFieldUiTest.php index 5da0416c44c7b211b883cfd1eda1c39c98571944..626046ee2535ae8d4ee9306fed5d16a6592c9082 100644 --- a/web/modules/token/tests/src/Functional/TokenFieldUiTest.php +++ b/web/modules/token/tests/src/Functional/TokenFieldUiTest.php @@ -22,18 +22,16 @@ class TokenFieldUiTest extends TokenTestBase { protected $adminUser; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['field_ui', 'node', 'image']; + protected static $modules = ['field_ui', 'node', 'image']; /** * {@inheritdoc} */ - public function setUp($modules = []) { + public function setUp(): void { parent::setUp(); - $this->adminUser = $this->drupalCreateUser(['administer content types', 'administer node fields']); + $this->adminUser = $this->drupalCreateUser(['bypass node access', 'administer content types', 'administer node fields']); $this->drupalLogin($this->adminUser); $node_type = NodeType::create([ @@ -108,18 +106,19 @@ public function testFileFieldUi() { $this->assertSession()->linkByHrefExists('token/tree'); // Ensure that the default file directory value validates correctly. - $this->drupalPostForm(NULL, [], 'Save settings'); - $this->assertText(t('Saved Image configuration.')); + $this->submitForm([], 'Save settings'); + $this->assertSession()->pageTextContains('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('admin/structure/types/manage/article/fields/node.article.field_body'); + $this->submitForm($edit, 'Save settings'); $this->drupalGet('node/add/article'); - $this->assertText('The site is called Drupal.'); + $this->assertSession()->pageTextContains('The site is called Drupal.'); } /** diff --git a/web/modules/token/tests/src/Functional/TokenMenuTest.php b/web/modules/token/tests/src/Functional/TokenMenuTest.php index 532f05971e98499118ff81569f3c17c71cbac3db..8b1c696acd9c9a5115e91d270f8c9c4a91645eaf 100644 --- a/web/modules/token/tests/src/Functional/TokenMenuTest.php +++ b/web/modules/token/tests/src/Functional/TokenMenuTest.php @@ -18,11 +18,9 @@ class TokenMenuTest extends TokenTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = [ + protected static $modules = [ 'menu_ui', 'node', 'block', @@ -153,11 +151,12 @@ function testMenuTokens() { 'menu_options[main]' => 1, 'menu_parent' => 'main-menu:', ]; - $this->drupalPostForm('admin/structure/types/manage/page', $edit, 'Save content type'); + $this->drupalGet('admin/structure/types/manage/page'); + $this->submitForm($edit, 'Save content type'); // Use a menu-link token in the body. $this->drupalGet('node/add/page'); - $this->drupalPostForm(NULL, [ + $this->submitForm([ // This should get replaced on save. // @see token_module_test_node_presave() 'title[0][value]' => 'Node menu title test', @@ -171,9 +170,11 @@ function testMenuTokens() { // 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], 'Save'); - $this->assertText('Menu Main menu has been updated.'); - $this->drupalPostForm('node/' . $node->id() . '/edit', [], 'Save'); + $this->drupalGet('admin/structure/menu/manage/main-menu'); + $this->submitForm(['links[menu_plugin_id:' . $link['id'] . '][enabled]' => FALSE], 'Save'); + $this->assertSession()->pageTextContains('Menu Main menu has been updated.'); + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm([], 'Save'); $this->assertSession()->linkNotExists('Test preview'); // Now test a parent link and token. @@ -190,7 +191,7 @@ function testMenuTokens() { return strpos($element->getText(), 'Test preview') !== FALSE; }); $this->assertCount(1, $options); - $this->drupalPostForm(NULL, [ + $this->submitForm([ '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, @@ -201,7 +202,8 @@ function testMenuTokens() { $this->assertEquals('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', [ + $this->drupalGet('node/' . $node->id() . '/edit'); + $this->submitForm([ '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', @@ -225,7 +227,7 @@ function testMenuTokens() { // Now add a new node with no menu. $this->drupalGet('node/add/page'); - $this->drupalPostForm(NULL, [ + $this->submitForm([ 'title[0][value]' => 'Node menu adding menu later test', 'body[0][value]' => 'Going to add a menu link on edit', 'menu[enabled]' => 0, @@ -233,7 +235,7 @@ function testMenuTokens() { $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, [ + $this->submitForm([ '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, @@ -247,6 +249,7 @@ function testMenuTokens() { $this->assertNotEmpty($link['entity_id']); $query = \Drupal::entityQuery('menu_link_content') ->condition('link.uri', 'entity:node/' . $node->id()) + ->accessCheck(TRUE) ->sort('id', 'ASC') ->range(0, 1); $result = $query->execute(); @@ -260,8 +263,9 @@ function testMenuTokens() { 'menu[enabled]' => 1, 'menu[title]' => 'menu link provided by node', ]; - $this->drupalPostForm('node/add/page', $edit, 'Save'); - $this->assertText('page ' . $node_title . ' has been created'); + $this->drupalGet('node/add/page'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('page ' . $node_title . ' has been created'); $node = $this->drupalGetNodeByTitle($node_title); $menu_ui_link1 = MenuLinkContent::create([ @@ -303,6 +307,7 @@ function testMultilingualMenu() { // Create the article content type. $node_type = NodeType::create([ 'type' => 'article', + 'name' => 'Article', ]); $node_type->save(); @@ -328,8 +333,8 @@ function testMultilingualMenu() { 'settings[node][article][fields][title]' => TRUE, 'settings[menu_link_content][menu_link_content][translatable]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, 'Save configuration'); - $this->assertText('Settings successfully updated.'); + $this->submitForm($edit, 'Save configuration'); + $this->assertSession()->pageTextContains('Settings successfully updated.'); // Create an english node with an english menu. $this->drupalGet('/node/add/article'); @@ -338,8 +343,9 @@ function testMultilingualMenu() { 'menu[enabled]' => TRUE, 'menu[title]' => 'English menu title', ]; - $this->drupalPostForm('/node/add/article', $edit, 'Save'); - $this->assertText('English test node with menu has been created.'); + $this->drupalGet('/node/add/article'); + $this->submitForm($edit, 'Save'); + $this->assertSession()->pageTextContains('English test node with menu has been created.'); // Add a german translation. $this->drupalGet('node/1/translations'); @@ -349,8 +355,8 @@ function testMultilingualMenu() { 'menu[enabled]' => TRUE, 'menu[title]' => 'German menu title', ]; - $this->drupalPostForm(NULL, $edit, 'Save (this translation)'); - $this->assertText('German test node with menu has been updated.'); + $this->submitForm($edit, 'Save (this translation)'); + $this->assertSession()->pageTextContains('German test node with menu has been updated.'); // Verify that the menu links are correct. $this->drupalGet('node/1'); diff --git a/web/modules/token/tests/src/Functional/TokenMenuUiContentModerationTest.php b/web/modules/token/tests/src/Functional/TokenMenuUiContentModerationTest.php index 0c8e269ea68e40e4fd3d30ed63e13ffe86a838f5..a9714c7c4be955f557ee0e2fa67422afd4984ef7 100644 --- a/web/modules/token/tests/src/Functional/TokenMenuUiContentModerationTest.php +++ b/web/modules/token/tests/src/Functional/TokenMenuUiContentModerationTest.php @@ -14,6 +14,6 @@ class TokenMenuUiContentModerationTest extends MenuUiContentModerationTest { /** * {@inheritdoc} */ - public static $modules = ['token']; + protected static $modules = ['token']; } diff --git a/web/modules/token/tests/src/Functional/TokenTestBase.php b/web/modules/token/tests/src/Functional/TokenTestBase.php index fda4898b91b45d8b2b6a41485e69dea0fb8d85aa..20d559685f20dfcb3201dc63c7d1ce5049ca716a 100644 --- a/web/modules/token/tests/src/Functional/TokenTestBase.php +++ b/web/modules/token/tests/src/Functional/TokenTestBase.php @@ -12,11 +12,9 @@ abstract class TokenTestBase extends BrowserTestBase { use TokenTestTrait; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['path', 'token', 'token_module_test']; + protected static $modules = ['path', 'token', 'token_module_test']; /** * {@inheritdoc} diff --git a/web/modules/token/tests/src/Functional/TokenURLTest.php b/web/modules/token/tests/src/Functional/TokenURLTest.php index a8d27f282dc6af3d3da881da46d6eb42dc6d2f6c..4668c7a7bbba619ca3a0ee3bba69343a70fc088e 100644 --- a/web/modules/token/tests/src/Functional/TokenURLTest.php +++ b/web/modules/token/tests/src/Functional/TokenURLTest.php @@ -12,16 +12,14 @@ class TokenURLTest extends TokenTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node']; + protected static $modules = ['node']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->saveAlias('/node/1', '/first-node'); } diff --git a/web/modules/token/tests/src/Functional/TokenUserTest.php b/web/modules/token/tests/src/Functional/TokenUserTest.php index 8ff3744bc4749c7f802d570cee14f7d6b0d68c0f..ff146cde74f77195c14d95e24f2a0a4097bd52bd 100644 --- a/web/modules/token/tests/src/Functional/TokenUserTest.php +++ b/web/modules/token/tests/src/Functional/TokenUserTest.php @@ -25,16 +25,14 @@ class TokenUserTest extends TokenTestBase { protected $account = NULL; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['token_user_picture']; + protected static $modules = ['token_user_picture']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->account = $this->drupalCreateUser([ @@ -62,7 +60,8 @@ public function testUserTokens() { // Add a user picture to the account. $image = current($this->getTestFiles('image')); $edit = ['files[user_picture_0]' => \Drupal::service('file_system')->realpath($image->uri)]; - $this->drupalPostForm('user/' . $this->account->id() . '/edit', $edit, 'Save'); + $this->drupalGet('user/' . $this->account->id() . '/edit'); + $this->submitForm($edit, 'Save'); $storage = \Drupal::entityTypeManager()->getStorage('user'); @@ -124,7 +123,7 @@ public function testUserTokens() { */ 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->assertSession()->pageTextContains('The list of available tokens that can be used in e-mails is provided below.'); $this->assertSession()->linkExists('Browse available tokens.'); $this->assertSession()->linkByHrefExists('token/tree'); } diff --git a/web/modules/token/tests/src/Functional/Tree/AutocompleteTest.php b/web/modules/token/tests/src/Functional/Tree/AutocompleteTest.php deleted file mode 100644 index 1f6f4034ba40b9332af909299898f79a1ac3ac0d..0000000000000000000000000000000000000000 --- a/web/modules/token/tests/src/Functional/Tree/AutocompleteTest.php +++ /dev/null @@ -1,78 +0,0 @@ -<?php - -namespace Drupal\Tests\token\Functional\Tree; - -use Drupal\Component\Serialization\Json; -use Drupal\Tests\token\Functional\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 = Json::decode($this->drupalGet($url, [ - 'query' => [ - '_format' => 'json', - ], - ])); - - $this->assertArrayHasKey('[node:nid]', $response); - $this->assertArrayHasKey('[node:author]', $response); - $this->assertArrayHasKey('[node:url]', $response); - $this->assertArrayHasKey('[node:url:', $response); - - $url = $url_prefix . 'Title of [node:url:'; - $response = Json::decode($this->drupalGet($url, [ - 'query' => [ - '_format' => 'json', - ], - ])); - - $this->assertArrayHasKey('[node:url:path]', $response); - $this->assertArrayHasKey('[node:url:absolute]', $response); - } - - /** - * Tests autocomplete for user tokens. - */ - public function testUserAutocomplete() { - $url_prefix = "token/autocomplete/user/"; - - $url = $url_prefix . 'Name of the [us'; - $response = Json::decode($this->drupalGet($url, [ - 'query' => [ - '_format' => 'json', - ], - ])); - - $this->assertArrayHasKey('[user:uid]', $response); - $this->assertArrayHasKey('[user:original]', $response); - $this->assertArrayHasKey('[user:url]', $response); - $this->assertArrayHasKey('[user:url:', $response); - - $url = $url_prefix . 'Title of [user:original:'; - $response = Json::decode($this->drupalGet($url, [ - 'query' => [ - '_format' => 'json', - ], - ])); - - $this->assertArrayHasKey('[user:original:uid]', $response); - } -} diff --git a/web/modules/token/tests/src/Functional/Tree/HelpPageTest.php b/web/modules/token/tests/src/Functional/Tree/HelpPageTest.php index 719fb0f850f85452366884bf9b180ec1038a519f..f32081203df19c43d6c28096762da33a08258599 100644 --- a/web/modules/token/tests/src/Functional/Tree/HelpPageTest.php +++ b/web/modules/token/tests/src/Functional/Tree/HelpPageTest.php @@ -19,13 +19,11 @@ class HelpPageTest extends TokenTestBase { protected $account; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['help']; + protected static $modules = ['help']; - public function setUp() { + public function setUp(): void { parent::setUp(); $this->account = $this->drupalCreateUser(['access administration pages']); @@ -37,7 +35,7 @@ public function setUp() { */ public function testHelpPageTree() { $this->drupalGet('admin/help/token'); - $this->assertText('The list of the currently available tokens on this site are shown below.'); + $this->assertSession()->pageTextContains('The list of the currently available tokens on this site are shown below.'); $this->assertTokenGroup('Current date'); $this->assertTokenGroup('Site information'); diff --git a/web/modules/token/tests/src/Functional/Tree/TreeTest.php b/web/modules/token/tests/src/Functional/Tree/TreeTest.php index c1c81104b7078f0f84ae7c9270a4937eccfbba6d..515295b129b74998207bd98fbfbf6b8323da6801 100644 --- a/web/modules/token/tests/src/Functional/Tree/TreeTest.php +++ b/web/modules/token/tests/src/Functional/Tree/TreeTest.php @@ -20,13 +20,11 @@ class TreeTest extends TokenTestBase { protected $account; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node']; + protected static $modules = ['node']; - public function setUp() { + public function setUp(): void { parent::setUp(); $this->account = $this->drupalCreateUser(['administer account settings']); @@ -96,7 +94,7 @@ public function testUserTokens() { // 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->assertEquals('MISS', $this->drupalGetHeader('x-drupal-dynamic-cache'), 'Cache was not hit'); + $this->assertEquals('MISS', $this->getSession()->getResponseHeader('x-drupal-dynamic-cache'), 'Cache was not hit'); $this->assertTokenInTree('[user:one-time-login-url]', 'user'); $this->assertTokenInTree('[user:original:cancel-url]', 'user--original'); } diff --git a/web/modules/token/tests/src/Functional/UrlTest.php b/web/modules/token/tests/src/Functional/UrlTest.php index 107629bbe80338861d448ed3281b682b99b1a002..565dff89a9940ab1ceecc1f149c6f6dff1faafec 100644 --- a/web/modules/token/tests/src/Functional/UrlTest.php +++ b/web/modules/token/tests/src/Functional/UrlTest.php @@ -32,11 +32,9 @@ class UrlTest extends BrowserTestBase { protected $node2; /** - * Modules to install. - * - * @var string[] + * {@inheritdoc} */ - public static $modules = ['node', 'token', 'block']; + protected static $modules = ['node', 'token', 'block']; /** * {@inheritdoc} @@ -46,7 +44,7 @@ class UrlTest extends BrowserTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $node_type = NodeType::create(['type' => 'article', 'name' => 'Article']); diff --git a/web/modules/token/tests/src/Kernel/BookTest.php b/web/modules/token/tests/src/Kernel/BookTest.php index 215fdb54e27f352d81fbc939c7cf4fd32b6308aa..75181f15769538ea6d89c2533e85fadceb53ddc1 100644 --- a/web/modules/token/tests/src/Kernel/BookTest.php +++ b/web/modules/token/tests/src/Kernel/BookTest.php @@ -13,16 +13,22 @@ class BookTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['user', 'field', 'filter', 'text', 'node', 'book']; + protected static $modules = [ + 'user', + 'field', + 'filter', + 'text', + 'node', + 'book', + ]; + /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); diff --git a/web/modules/token/tests/src/Kernel/CommentTest.php b/web/modules/token/tests/src/Kernel/CommentTest.php index 8054ed20f5d4b37b1f2d6f41faaee218310e8820..9c62e9a5bda30e3cec6a9e97bfc215634f16e3e5 100644 --- a/web/modules/token/tests/src/Kernel/CommentTest.php +++ b/web/modules/token/tests/src/Kernel/CommentTest.php @@ -18,16 +18,19 @@ class CommentTest extends KernelTestBase { use CommentTestTrait; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node', 'comment', 'field', 'text', 'entity_reference']; + protected static $modules = [ + 'node', + 'comment', + 'field', + 'text', + ]; /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('node'); diff --git a/web/modules/token/tests/src/Kernel/DateTest.php b/web/modules/token/tests/src/Kernel/DateTest.php index c120e1109eb298725ec1335aa04a64489a273b46..47bf5be018f46dcabb2fe7d97d480031bbe6fb17 100644 --- a/web/modules/token/tests/src/Kernel/DateTest.php +++ b/web/modules/token/tests/src/Kernel/DateTest.php @@ -10,16 +10,14 @@ class DateTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = []; + protected static $modules = []; /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installConfig(['system', 'token_module_test']); } diff --git a/web/modules/token/tests/src/Kernel/EntityTest.php b/web/modules/token/tests/src/Kernel/EntityTest.php index 44501f7fd89adb433bc5cea698a3366211976d03..558750d55d054cb677c0e21dcef6faaafba61e6d 100644 --- a/web/modules/token/tests/src/Kernel/EntityTest.php +++ b/web/modules/token/tests/src/Kernel/EntityTest.php @@ -15,16 +15,14 @@ class EntityTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node', 'taxonomy', 'text']; + protected static $modules = ['node', 'taxonomy', 'text']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); // Create the default tags vocabulary. diff --git a/web/modules/token/tests/src/Kernel/FieldTest.php b/web/modules/token/tests/src/Kernel/FieldTest.php index 345ae676d613a828ea0358557cb108680f06fb1c..d49038dc925b7730f69ce9b9ff486ded0d091e7c 100644 --- a/web/modules/token/tests/src/Kernel/FieldTest.php +++ b/web/modules/token/tests/src/Kernel/FieldTest.php @@ -42,16 +42,25 @@ class FieldTest extends KernelTestBase { protected $vocabulary; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node', 'text', 'field', 'filter', 'contact', 'options', 'taxonomy', 'language', 'datetime', 'datetime_range']; + protected static $modules = [ + 'node', + 'text', + 'field', + 'filter', + 'contact', + 'options', + 'taxonomy', + 'language', + 'datetime', + 'datetime_range', + ]; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); @@ -97,6 +106,7 @@ public function setUp() { $this->testFormat = FilterFormat::create([ 'format' => 'test', + 'name' => 'Test format', 'weight' => 1, 'filters' => [ 'filter_html_escape' => ['status' => TRUE], diff --git a/web/modules/token/tests/src/Kernel/FileTest.php b/web/modules/token/tests/src/Kernel/FileTest.php index 6cfa98875b191c58256743225699b32958455484..b3d7a2e7c8525fdf458a43a04ac12e59104f8a5c 100644 --- a/web/modules/token/tests/src/Kernel/FileTest.php +++ b/web/modules/token/tests/src/Kernel/FileTest.php @@ -11,16 +11,14 @@ class FileTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['file']; + protected static $modules = ['file']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->installEntitySchema('file'); } diff --git a/web/modules/token/tests/src/Kernel/KernelTestBase.php b/web/modules/token/tests/src/Kernel/KernelTestBase.php index c272215ab203e144bdfd1f73125ff2a4006cf7e1..0ccaafb32c2779fe6a3cf6226d4d70dd6bd5ebb5 100644 --- a/web/modules/token/tests/src/Kernel/KernelTestBase.php +++ b/web/modules/token/tests/src/Kernel/KernelTestBase.php @@ -13,16 +13,21 @@ abstract class KernelTestBase extends BaseKernelTestBase { use TokenTestTrait; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['path', 'token', 'token_module_test', 'system', 'user', 'path_alias']; + protected static $modules = [ + 'path', + 'token', + 'token_module_test', + 'system', + 'user', + 'path_alias', + ]; /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('path_alias'); diff --git a/web/modules/token/tests/src/Kernel/LanguageTest.php b/web/modules/token/tests/src/Kernel/LanguageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..496b4015c08a5a52c2cbb9540986aab99c39ce22 --- /dev/null +++ b/web/modules/token/tests/src/Kernel/LanguageTest.php @@ -0,0 +1,367 @@ +<?php + +namespace Drupal\Tests\token\Kernel; + +use Drupal\Core\Language\Language; +use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Render\BubbleableMetadata; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\Core\DependencyInjection\ContainerBuilder; + +/** + * Tests language tokens. + * + * @group token + */ +class LanguageTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'language', + 'token', + ]; + + /** + * Language codes of languages to enable during the test. + * + * @var array + */ + protected $langcodes = ['bg', 'hu', 'nl', 'pt-pt']; + + /** + * An array of languages used during the test, keyed by language code. + * + * @var \Drupal\language\Entity\ConfigurableLanguage[] + */ + protected $languages = []; + + /** + * Language prefixes used during the test. + * + * @var array + */ + protected $language_prefixes = []; + + /** + * Language domains used during the test. + * + * @var array + */ + protected $language_domains = []; + + /** + * The token replacement service. + * + * @var \Drupal\Core\Utility\Token + */ + protected $token; + + /** + * The mock language manager service. + * + * @var \Drupal\Tests\token\Kernel\MockLanguageManager + */ + protected $languageManager; + + /** + * {@inheritdoc} + */ + public function register(ContainerBuilder $container) { + parent::register($container); + + // Use Portuguese as the default language during the test. We're not using + // English so we can detect if the default language is correctly honored. + $language = Language::$defaultValues; + $language['id'] = 'pt-pt'; + $language['name'] = 'Portuguese, Portugal'; + $container->setParameter('language.default_values', $language); + $this->container + ->register('language.default', 'Drupal\Core\Language\LanguageDefault') + ->addArgument('%language.default_values%'); + } + + /** + * {@inheritdoc} + */ + protected function setUp(): void { + parent::setUp(); + + $this->token = $this->container->get('token'); + + // Use a version of the language manager in which the various languages can + // be easily overridden during the test. We need to do this here instead of + // in ::register() since the container is being altered by + // LanguageServiceProvider::alter() after the services have been registered. + $this->languageManager = new MockLanguageManager( + $this->container->get('language.default'), + $this->container->get('config.factory'), + $this->container->get('module_handler'), + $this->container->get('language.config_factory_override'), + $this->container->get('request_stack') + ); + $this->container->set('language_manager', $this->languageManager); + + foreach ($this->langcodes as $langcode) { + // Enable test languages. + $this->languages[$langcode] = ConfigurableLanguage::createFromLangcode($langcode); + $this->languages[$langcode]->save(); + + // Populate language prefixes and domains to use in the test. + $this->language_prefixes[$langcode] = "$langcode-prefix"; + $this->language_domains[$langcode] = $langcode . '.example.com'; + } + + // Set language negotiation prefixes and domains to values that are uniquely + // identifiable in the test. + $language_negotiation_config = $this->config('language.negotiation'); + $language_negotiation_config->set('url.prefixes', $this->language_prefixes); + $language_negotiation_config->set('url.domains', $this->language_domains); + $language_negotiation_config->save(); + } + + /** + * Tests the language tokens. + * + * @dataProvider languageTokenReplacementDataProvider + */ + public function testLanguageTokenReplacement($token, $langcode, $expected_result) { + $bubbleable_metadata = new BubbleableMetadata(); + $options = $langcode ? ['langcode' => $langcode] : []; + // The part of the token name between the last `:` and the closing bracket + // is the machine name of the token. + preg_match('/\[.+:(.+)\]/', $token, $matches); + $name = $matches[1]; + $replacements = $this->token->generate('language', [$name => $token], [], $options, $bubbleable_metadata); + $this->assertEquals($expected_result, $replacements[$token]); + } + + /** + * Tests retrieving the interface and content language from the current page. + * + * @dataProvider currentPageLanguageTokenReplacementDataProvider + */ + public function testCurrentPageLanguageTokenReplacement($token, $langcode, $expected_result) { + // Set the interface language to Dutch. + $this->languageManager->setCurrentLanguage(LanguageInterface::TYPE_INTERFACE, $this->languages['nl']); + // Set the content language to Hungarian. + $this->languageManager->setCurrentLanguage(LanguageInterface::TYPE_CONTENT, $this->languages['hu']); + + $options = $langcode ? ['langcode' => $langcode] : []; + $result = $this->token->replace($token, [], $options); + $this->assertEquals($expected_result, $result); + } + + /** + * Provides test data for ::testLanguageTokenReplacement(). + * + * @return array + * An array of test cases. Each test case is an array with the following + * values: + * - The token to test. + * - An optional language code to pass as an option. + * - The expected result of the token replacement. + * + * @see testLanguageTokenReplacement() + */ + public function languageTokenReplacementDataProvider() { + return [ + [ + // Test the replacement of the name of the site default language. + '[language:name]', + // We are not overriding the language by passing a language code as an + // option. This means that the default language should be used which has + // been set to Portuguese. + NULL, + // The expected result. + 'Portuguese, Portugal', + ], + // Test the replacement of the other properties of the default language. + [ + '[language:langcode]', + NULL, + 'pt-pt', + ], + [ + '[language:direction]', + NULL, + 'ltr', + ], + [ + '[language:domain]', + NULL, + 'pt-pt.example.com', + ], + [ + '[language:prefix]', + NULL, + 'pt-pt-prefix', + ], + // Now repeat the entire test but override the language to use by passing + // Bulgarian as an option. + [ + '[language:name]', + 'bg', + 'Bulgarian', + ], + [ + '[language:langcode]', + 'bg', + 'bg', + ], + [ + '[language:direction]', + 'bg', + 'ltr', + ], + [ + '[language:domain]', + 'bg', + 'bg.example.com', + ], + [ + '[language:prefix]', + 'bg', + 'bg-prefix', + ], + ]; + } + + /** + * Provides test data for ::testCurrentPageLanguageTokenReplacement(). + * + * @return array + * An array of test cases. Each test case is an array with the following + * values: + * - The token to test. + * - An optional language code to pass as an option. + * - The expected result of the token replacement. + * + * @see testCurrentPageLanguageTokenReplacement() + */ + public function currentPageLanguageTokenReplacementDataProvider() { + return [ + [ + // Test the replacement of the language name token, taken from the + // interface language of the current page. + '[current-page:interface-language:name]', + // We are not overriding the language by passing a language code as an + // option. This means that the language should be taken from the + // interface language which has been set to Dutch. + NULL, + // The expected result. + 'Dutch', + ], + // Test the token name in the content language. + [ + '[current-page:content-language:name]', + NULL, + 'Hungarian', + ], + // Test the other tokens both for the content and interface languages. + [ + '[current-page:interface-language:langcode]', + NULL, + 'nl', + ], + [ + '[current-page:content-language:langcode]', + NULL, + 'hu', + ], + [ + '[current-page:interface-language:direction]', + NULL, + 'ltr', + ], + [ + '[current-page:content-language:direction]', + NULL, + 'ltr', + ], + [ + '[current-page:interface-language:domain]', + NULL, + 'nl.example.com', + ], + [ + '[current-page:content-language:domain]', + NULL, + 'hu.example.com', + ], + [ + '[current-page:interface-language:prefix]', + NULL, + 'nl-prefix', + ], + [ + '[current-page:content-language:prefix]', + NULL, + 'hu-prefix', + ], + // Now repeat the entire test with Bulgarian passed as an option. This + // should not affect the results, the language should be sourced from the + // current page. + [ + // Test the replacement of the language name token, taken from the + // interface language of the current page. + '[current-page:interface-language:name]', + // We are not overriding the language by passing a language code as an + // option. This means that the language should be taken from the + // interface language which has been set to Dutch. + 'bg', + // The expected result. + 'Dutch', + ], + // Test the token name in the content language. + [ + '[current-page:content-language:name]', + 'bg', + 'Hungarian', + ], + // Test the other tokens both for the content and interface languages. + [ + '[current-page:interface-language:langcode]', + 'bg', + 'nl', + ], + [ + '[current-page:content-language:langcode]', + 'bg', + 'hu', + ], + [ + '[current-page:interface-language:direction]', + 'bg', + 'ltr', + ], + [ + '[current-page:content-language:direction]', + 'bg', + 'ltr', + ], + [ + '[current-page:interface-language:domain]', + 'bg', + 'nl.example.com', + ], + [ + '[current-page:content-language:domain]', + 'bg', + 'hu.example.com', + ], + [ + '[current-page:interface-language:prefix]', + 'bg', + 'nl-prefix', + ], + [ + '[current-page:content-language:prefix]', + 'bg', + 'hu-prefix', + ], + ]; + } + +} diff --git a/web/modules/token/tests/src/Kernel/MockLanguageManager.php b/web/modules/token/tests/src/Kernel/MockLanguageManager.php new file mode 100644 index 0000000000000000000000000000000000000000..b2d7b72b0436711eb76f68ea6c195ab17f8fdb1f --- /dev/null +++ b/web/modules/token/tests/src/Kernel/MockLanguageManager.php @@ -0,0 +1,42 @@ +<?php + +namespace Drupal\Tests\token\Kernel; + +use Drupal\Core\Language\LanguageInterface; +use Drupal\language\ConfigurableLanguageManager; + +/** + * A language manager that can be easily overridden for testing purposes. + */ +class MockLanguageManager extends ConfigurableLanguageManager { + + /** + * List of current languages used in the test. + * + * @var \Drupal\Core\Language\LanguageInterface[] + */ + protected $currentLanguages; + + /** + * {@inheritdoc} + */ + public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) { + if (isset($this->currentLanguages[$type])) { + return $this->currentLanguages[$type]; + } + return parent::getCurrentLanguage($type); + } + + /** + * Sets the current language of the given type to use during tests. + * + * @param string $type + * The language type. + * @param \Drupal\Core\Language\LanguageInterface $language + * The language. + */ + public function setCurrentLanguage($type, LanguageInterface $language) { + $this->currentLanguages[$type] = $language; + } + +} diff --git a/web/modules/token/tests/src/Kernel/NodeTest.php b/web/modules/token/tests/src/Kernel/NodeTest.php index 846961a4db200b77ee80970c3bba8602fd15b04a..6e4116f94b7881c2b44f094bac53100809f6be44 100644 --- a/web/modules/token/tests/src/Kernel/NodeTest.php +++ b/web/modules/token/tests/src/Kernel/NodeTest.php @@ -14,16 +14,14 @@ class NodeTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['node', 'field', 'text']; + protected static $modules = ['node', 'field', 'text']; /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); @@ -68,6 +66,7 @@ function testNodeTokens() { 'type' => 'page', 'type-name' => 'Basic page', 'url:alias' => '/content/source-node', + 'language:name' => 'English' ]; $this->assertTokens('node', ['node' => $page], $tokens); @@ -93,6 +92,7 @@ function testNodeTokens() { 'type' => 'article', 'type-name' => 'Article', 'url:alias' => "/node/{$article->id()}", + 'language:name' => 'English' ]; $this->assertTokens('node', ['node' => $article], $tokens); } diff --git a/web/modules/token/tests/src/Kernel/TaxonomyTest.php b/web/modules/token/tests/src/Kernel/TaxonomyTest.php index abc99ea4d4fbe381c60afe5cc51a06907a387c68..c7b5a0e98e27515d1e1f910d004e5ee288e0ee17 100644 --- a/web/modules/token/tests/src/Kernel/TaxonomyTest.php +++ b/web/modules/token/tests/src/Kernel/TaxonomyTest.php @@ -17,16 +17,14 @@ class TaxonomyTest extends KernelTestBase { protected $vocab; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['taxonomy', 'text', 'language']; + protected static $modules = ['taxonomy', 'text', 'language']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->installEntitySchema('taxonomy_term'); diff --git a/web/modules/token/tests/src/Kernel/UnitTest.php b/web/modules/token/tests/src/Kernel/UnitTest.php index ee0f72570696b6adafddefe684a7f90f7561bbbf..0cadcb7934ad1e076ab8bb3c291545016e0e5860 100644 --- a/web/modules/token/tests/src/Kernel/UnitTest.php +++ b/web/modules/token/tests/src/Kernel/UnitTest.php @@ -15,16 +15,14 @@ class UnitTest extends KernelTestBase { protected $tokenService; /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['file', 'node']; + protected static $modules = ['file', 'node']; /** * {@inheritdoc} */ - public function setUp() { + public function setUp(): void { parent::setUp(); $this->tokenService = \Drupal::token(); } diff --git a/web/modules/token/tests/src/Kernel/UrlTest.php b/web/modules/token/tests/src/Kernel/UrlTest.php index 1464095d07bab8c2de08ac10eb8b8778c5d0f6ae..6de4a1cc8b59d72943cefa03719075ab0099f196 100644 --- a/web/modules/token/tests/src/Kernel/UrlTest.php +++ b/web/modules/token/tests/src/Kernel/UrlTest.php @@ -36,7 +36,7 @@ class UrlTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->token = $this->container->get('token'); $this->requestStack = $this->container->get('request_stack'); diff --git a/web/modules/token/tests/src/Kernel/ValidateD6MigrationStateTest.php b/web/modules/token/tests/src/Kernel/ValidateD6MigrationStateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a2c52d279138aa2a202b8e6ff8d8e2ddc905ecb5 --- /dev/null +++ b/web/modules/token/tests/src/Kernel/ValidateD6MigrationStateTest.php @@ -0,0 +1,26 @@ +<?php + +namespace Drupal\Tests\token\Kernel; + +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; +use Drupal\Tests\migrate_drupal\Traits\ValidateMigrationStateTestTrait; + +/** + * Tests that the token test has a declared D6 migration status. + * + * ValidateMigrationStateTestTrait::testMigrationState() will succeed if the + * modules enabled in \Drupal\Tests\KernelTestBase::bootKernel() have a valid + * migration status (i.e.: finished or not_finished); but will fail if they do + * not have a declared migration status. + * + * @group token + */ +class ValidateD6MigrationStateTest extends MigrateDrupal6TestBase { + use ValidateMigrationStateTestTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = ['token']; + +} diff --git a/web/modules/token/tests/src/Kernel/ValidateD7MigrationStateTest.php b/web/modules/token/tests/src/Kernel/ValidateD7MigrationStateTest.php new file mode 100644 index 0000000000000000000000000000000000000000..118276817428b0f744e818486dfe20a49ff13176 --- /dev/null +++ b/web/modules/token/tests/src/Kernel/ValidateD7MigrationStateTest.php @@ -0,0 +1,26 @@ +<?php + +namespace Drupal\Tests\token\Kernel; + +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; +use Drupal\Tests\migrate_drupal\Traits\ValidateMigrationStateTestTrait; + +/** + * Tests that the token test has a declared D7 migration status. + * + * ValidateMigrationStateTestTrait::testMigrationState() will succeed if the + * modules enabled in \Drupal\Tests\KernelTestBase::bootKernel() have a valid + * migration status (i.e.: finished or not_finished); but will fail if they do + * not have a declared migration status. + * + * @group token + */ +class ValidateD7MigrationStateTest extends MigrateDrupal7TestBase { + use ValidateMigrationStateTestTrait; + + /** + * {@inheritdoc} + */ + protected static $modules = ['token']; + +} diff --git a/web/modules/token/tests/src/Kernel/ViewsTest.php b/web/modules/token/tests/src/Kernel/ViewsTest.php index 884e4fcb4673a947c40694062f8693308fc821df..a24bcdc00e28b63171b3ddb2c7a021c83ef78eb7 100644 --- a/web/modules/token/tests/src/Kernel/ViewsTest.php +++ b/web/modules/token/tests/src/Kernel/ViewsTest.php @@ -13,11 +13,9 @@ class ViewsTest extends KernelTestBase { /** - * Modules to enable. - * - * @var array + * {@inheritdoc} */ - public static $modules = ['views', 'block']; + protected static $modules = ['views', 'block']; /** * Views used by this test. @@ -29,7 +27,7 @@ class ViewsTest extends KernelTestBase { /** * {@inheritdoc} */ - protected function setUp() { + protected function setUp(): void { parent::setUp(); $this->installEntitySchema('user'); ViewTestData::createTestViews(get_class($this), ['token_module_test']); diff --git a/web/modules/token/token.info.yml b/web/modules/token/token.info.yml index 03fb438b7beced159cba16ba745b728a4dae73a4..f0339a0c03b14ff46a4c5b888429d115fe85cee3 100644 --- a/web/modules/token/token.info.yml +++ b/web/modules/token/token.info.yml @@ -1,9 +1,9 @@ type: module name: Token description: Provides a user interface for the Token API and some missing core tokens. -core_version_requirement: ^8.8 || ^9 +core_version_requirement: ^9.2 || ^10 -# Information added by Drupal.org packaging script on 2020-12-18 -version: '8.x-1.9' +# Information added by Drupal.org packaging script on 2022-08-02 +version: '8.x-1.11' project: 'token' -datestamp: 1608284868 +datestamp: 1659471815 diff --git a/web/modules/token/token.install b/web/modules/token/token.install index 2360fb730d9855c1559fd36a02107293b4fa8e7e..8b32f74b717bdf931abaae506b6e1834a29bcd06 100644 --- a/web/modules/token/token.install +++ b/web/modules/token/token.install @@ -61,160 +61,6 @@ function token_install() { } } -/** - * Build a list of Drupal 6 tokens and their Drupal 7 token names. - */ -function _token_upgrade_token_list() { - $tokens = [ - // Global tokens - 'user-name' => 'current-user:name', - 'user-id' => 'current-user:id', - 'user-mail' => 'current-user:mail', - 'site-url' => 'site:url', - 'site-name' => 'site:name', - 'site-slogan' => 'site:slogan', - 'site-mission' => 'site:mission', - 'site-mail' => 'site:mail', - 'site-date' => 'date:short', - //'site-date-' => '', // Date tokens expanded below - 'current-page-path' => 'current-page:path', - 'current-page-url' => 'current-page:url', - 'page-number' => 'current-page:page-number', - - // Comment tokens - 'comment-cid' => 'comment:cid', - 'comment-nid' => 'comment:node:nid', - 'comment-title' => 'comment:title', - 'comment-body' => 'comment:body', - 'comment-author-name' => 'comment:author:name', - 'comment-author-mail' => 'comment:author:mail', - //'comment-body-format' => '', - //'comment-' => '', // Date tokens expanded below - 'comment-node-title' => 'comment:node', - - // Node tokens - 'nid' => 'node:nid', - 'type' => 'node:type', - 'type-name' => 'node:type-name', - 'language' => 'node:language', - 'title' => 'node:title', - 'author-uid' => 'node:author:uid', - 'author-name' => 'node:author:name', - 'author-mail' => 'node:author:mail', - 'node_comment_count' => 'node:comment-count', - 'unread_comment_count' => 'node:comment-count-new', - 'log' => 'node:log', - //'' => '', // Date tokens expanded below - //'mod-' => '', // Date tokens expanded below - 'menupath' => 'node:menu-link:parent:path][node:menu-link', - 'menu' => 'node:menu-link:menu-name', - 'menu-link-title' => 'node:menu-link', - 'menu-link-mlid' => 'node:menu-link:mlid', - 'menu-link-plid' => 'node:menu-link:parent:mlid', - //'term' => 'node:term', - //'term-id' => 'node:term:tid', - //'vocab' => 'node:term:vocabulary', - //'vocab-id' => 'node:term:vocabulary:vid', - - // Book tokens - //'book' => 'node:book', - //'book_id' => 'node:book:bid', - //'bookpath' => 'node:book:path', - - // Taxonomy tokens - 'tid' => 'term:tid', - 'cat' => 'term:name', - 'cat-description' => 'term:description', - 'vid' => 'term:vocabulary:vid', - 'vocab' => 'term:vocabulary', - 'vocab-description' => 'term:vocabulary:description', - - // User tokens - 'user' => 'user:name', - 'uid' => 'user:uid', - 'mail' => 'user:mail', - 'reg-date' => 'user:created', - 'reg-since' => 'user:created:since', - //'user-created' => '', // Date tokens expanded below - 'log-date' => 'user:last-login', - 'log-since' => 'user:last-login:since', - //'user-last-login' => '', // Date tokens expanded below - //'date-in-tz' => '', - 'account-url' => 'user:url', - 'account-edit' => 'user:edit-url', - ]; - - // Account for date tokens which need to be expanded. - $tokens += _token_upgrade_token_date_list('site-', 'site:date'); - $tokens += _token_upgrade_token_date_list('', 'node:created'); - $tokens += _token_upgrade_token_date_list('mod-', 'node:changed'); - //$tokens += _token_upgrade_token_date_list('node-revision-', 'node:changed'); - $tokens += _token_upgrade_token_date_list('comment-', 'comment:created'); - $tokens += _token_upgrade_token_date_list('user-register-', 'user:created'); - $tokens += _token_upgrade_token_date_list('user-last-login-', 'user:last-login'); - - return $tokens; -} - -/** - * Build a list of Drupal 6 date tokens and their Drupal 7 token names. - */ -function _token_upgrade_token_date_list($old_token, $new_token) { - $tokens = []; - $formats = [ - 'yyyy' => 'Y', - 'yy' => 'y', - 'month' => 'F', - 'mon' => 'M', - 'mm' => 'm', - 'm' => 'n', - 'ww' => 'W', - 'date' => 'N', - 'day' => 'l', - 'ddd' => 'D', - 'dd' => 'd', - 'd' => 'j', - ]; - foreach ($formats as $token_format => $date_format) { - $tokens[$old_token . $token_format] = "$new_token:custom:$date_format"; - } - $tokens[$old_token . 'raw'] = "$new_token:raw"; - $tokens[$old_token . 'since'] = "$new_token:since"; - return $tokens; -} - -/** - * Update a string containing Drupal 6 style tokens to Drupal 7 style tokens. - * - * @param $text - * A string containing tokens. - * @param $updates - * An optional array of Drupal 7 tokens keyed by their Drupal 6 token name. - * The default tokens will be merged into this array. Note neither the old - * or new token names should include the surrounding bracket ([ and ]) - * characters. - * @return - * A string with the tokens upgraded - * - * @see _token_upgrade_token_list() - */ -function token_update_token_text($text, $updates = [], $leading = '[', $trailing = ']') { - $updates += _token_upgrade_token_list(); - $regex = '/' . preg_quote($leading, '/') . '([^\s]*)' . preg_quote($trailing, '/') . '/'; - preg_match_all($regex, $text, $matches); - - foreach ($matches[1] as $old_token) { - if (isset($updates[$old_token])) { - $new_token = $updates[$old_token]; - $text = str_replace("{$leading}{$old_token}{$trailing}", "[$new_token]", $text); - // Also replace any tokens that have a -raw suffix. - $text = str_replace("{$leading}{$old_token}-raw{$trailing}", "[$new_token]", $text); - } - } - - return $text; -} - /** * Get token problems. */ diff --git a/web/modules/token/token.libraries.yml b/web/modules/token/token.libraries.yml index 5c7ca14d1861e900f09d01947c0797bf33c05762..c5e390a0e771f910b5f554ac34ef08144a93869b 100644 --- a/web/modules/token/token.libraries.yml +++ b/web/modules/token/token.libraries.yml @@ -23,3 +23,5 @@ token: dependencies: - core/jquery - core/drupal + - core/once + - token/jquery.treeTable diff --git a/web/modules/token/token.module b/web/modules/token/token.module index 2299984ddef5132ea20d398b0703d619920dce3a..ff0c3dbf45b0d5753943e5ee376eff53aefff1e1 100644 --- a/web/modules/token/token.module +++ b/web/modules/token/token.module @@ -267,7 +267,7 @@ function _token_module($type, $name) { function token_element_validate($element, FormStateInterface $form_state) { $value = isset($element['#value']) ? $element['#value'] : $element['#default_value']; - if (!mb_strlen($value)) { + if (empty($value)) { // Empty value needs no further validation since the element should depend // on using the '#required' FAPI property. return $element; diff --git a/web/modules/token/token.routing.yml b/web/modules/token/token.routing.yml index f2105aeaf762366036ecb9399bf942601d6014d8..a3d062f12508cf04a4b850317239317c4c95d056 100644 --- a/web/modules/token/token.routing.yml +++ b/web/modules/token/token.routing.yml @@ -5,13 +5,6 @@ token.tree: requirements: _csrf_token: 'TRUE' -token.autocomplete: - path: '/token/autocomplete/{token_type}/{filter}' - defaults: - _controller: '\Drupal\token\Controller\TokenAutocompleteController::autocomplete' - requirements: - _access: 'TRUE' - token.flush_cache: path: '/token/flush-cache' defaults: diff --git a/web/modules/token/token.tokens.inc b/web/modules/token/token.tokens.inc index 1ac3f657645ecc5eea7ac3b1656762f60d58126f..7b2e2cfa3c34bda922bddcef5b877b91dcd8168d 100755 --- a/web/modules/token/token.tokens.inc +++ b/web/modules/token/token.tokens.inc @@ -9,10 +9,10 @@ use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\TypedData\EntityDataDefinitionInterface; +use Drupal\Core\Language\LanguageInterface; use Drupal\Core\Render\BubbleableMetadata; -use Drupal\Core\Render\Element; -use Drupal\Component\Utility\Crypt; use Drupal\Component\Utility\Html; +use Drupal\Core\Routing\RouteObjectInterface; use Drupal\Core\TypedData\DataReferenceDefinitionInterface; use Drupal\Core\Url; use Drupal\field\FieldStorageConfigInterface; @@ -22,8 +22,6 @@ use Drupal\node\NodeInterface; use Drupal\system\Entity\Menu; use Drupal\user\UserInterface; -use Symfony\Cmf\Component\Routing\RouteObjectInterface; -use Drupal\Core\TypedData\PrimitiveInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\image\Entity\ImageStyle; @@ -91,6 +89,16 @@ function token_token_info_alter(&$info) { ]; } + // Add [entity:language] tokens if they do not already exist. + if (!isset($info['tokens'][$token_type]['language'])) { + $info['tokens'][$token_type]['language'] = [ + 'name' => t('Language'), + 'description' => t('The language of the @entity.', ['@entity' => mb_strtolower($entity_info->getLabel())]), + 'module' => 'token', + 'type' => 'language', + ]; + } + // Add [entity:original] tokens if they do not already exist. if (!isset($info['tokens'][$token_type]['original'])) { $info['tokens'][$token_type]['original'] = [ @@ -271,6 +279,32 @@ function token_token_info() { 'type' => 'menu-link', ]; + // Language tokens. + $info['types']['language'] = [ + 'name' => t('Language'), + 'description' => t('Tokens related to site language.'), + ]; + $info['tokens']['language']['name'] = [ + 'name' => t('Language name'), + 'description' => t('The language name.'), + ]; + $info['tokens']['language']['langcode'] = [ + 'name' => t('Language code'), + 'description' => t('The language code.'), + ]; + $info['tokens']['language']['direction'] = [ + 'name' => t('Direction'), + 'description' => t('Whether the language is written left-to-right (ltr) or right-to-left (rtl).'), + ]; + $info['tokens']['language']['domain'] = [ + 'name' => t('Domain'), + 'description' => t('The domain name to use for the language.'), + ]; + $info['tokens']['language']['prefix'] = [ + 'name' => t('Path prefix'), + 'description' => t('Path prefix for URLs in the language.'), + ]; + // Current page tokens. $info['types']['current-page'] = [ 'name' => t('Current page'), @@ -294,6 +328,16 @@ function token_token_info() { 'description' => t('The value of a specific query string field of the current page.'), 'dynamic' => TRUE, ]; + $info['tokens']['current-page']['interface-language'] = [ + 'name' => t('Interface language'), + 'description' => t('The active user interface language.'), + 'type' => 'language', + ]; + $info['tokens']['current-page']['content-language'] = [ + 'name' => t('Content language'), + 'description' => t('The active content language.'), + 'type' => 'language', + ]; // URL tokens. $info['types']['url'] = [ @@ -521,6 +565,7 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea $count = \Drupal::entityQueryAggregate('node') ->aggregate('nid', 'COUNT') ->condition('type', $node_type->id()) + ->accessCheck(TRUE) ->execute(); $replacements[$original] = (int) $count; break; @@ -751,6 +796,42 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea } + // Language tokens. + if ($type == 'language' && !empty($langcode)) { + $language = $language_manager->getLanguage($langcode); + if ($language) { + foreach ($tokens as $name => $original) { + switch ($name) { + case 'name': + $replacements[$original] = $language->getName(); + break; + case 'langcode': + $replacements[$original] = $langcode; + break; + case 'direction': + $replacements[$original] = $language->getDirection(); + break; + case 'domain': + if (!isset($language_url_domains)) { + $language_url_domains = \Drupal::config('language.negotiation')->get('url.domains'); + } + if (isset($language_url_domains[$langcode])) { + $replacements[$original] = $language_url_domains[$langcode]; + } + break; + case 'prefix': + if (!isset($language_url_prefixes)) { + $language_url_prefixes = \Drupal::config('language.negotiation')->get('url.prefixes'); + } + if (isset($language_url_prefixes[$langcode])) { + $replacements[$original] = $language_url_prefixes[$langcode]; + } + break; + } + } + } + } + // Current page tokens. if ($type == 'current-page') { $request = \Drupal::request(); @@ -795,6 +876,18 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea $replacements[$original] = (int) $page + 1; break; } + // [current-page:interface-language:*] chained tokens. + if ($language_interface_tokens = \Drupal::token()->findWithPrefix($tokens, 'interface-language')) { + $language_interface = $language_manager->getCurrentLanguage(LanguageInterface::TYPE_INTERFACE); + $langcode = $language_interface->getId(); + $replacements += \Drupal::token()->generate('language', $language_interface_tokens, $data, ['langcode' => $langcode] + $options, $bubbleable_metadata); + } + // [current-page:content-language:*] chained tokens. + if ($language_content_tokens = \Drupal::token()->findWithPrefix($tokens, 'content-language')) { + $language_content = $language_manager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); + $langcode = $language_content->getId(); + $replacements += \Drupal::token()->generate('language', $language_content_tokens, $data, ['langcode' => $langcode] + $options, $bubbleable_metadata); + } } // @deprecated @@ -948,6 +1041,12 @@ function token_tokens($type, array $tokens, array $data, array $options, Bubblea $replacements += \Drupal::token()->generate($type, $original_tokens, [$type => $entity->original], $options, $bubbleable_metadata); } + // [entity:language:*] chained tokens. + if (($language_tokens = \Drupal::token()->findWithPrefix($tokens, 'language')) && _token_module($type, 'language') == 'token') { + $language_options = array_merge($options, ['langcode' => $entity->get('langcode')->value]); + $replacements += \Drupal::token()->generate('language', $language_tokens, [], $language_options, $bubbleable_metadata); + } + // Pass through to an generic 'entity' token type generation. $entity_data = [ 'entity_type' => $entity_type, @@ -1601,7 +1700,7 @@ function field_tokens($type, $tokens, array $data, array $options, BubbleableMet // For [entity:field_name:0], [entity:field_name:0:value] and // [entity:field_name:value] tokens. else { - list($field_name, $delta) = explode(':', $name, 2); + [$field_name, $delta] = explode(':', $name, 2); if (!is_numeric($delta)) { unset($delta); }