Update to Drupal 8.0.0 beta 14. For more information, see https://drupal.org/node/2544542
This commit is contained in:
parent
3b2511d96d
commit
81ccda77eb
2155 changed files with 54307 additions and 46870 deletions
|
@ -79,7 +79,8 @@
|
|||
// asynchronously.
|
||||
Drupal.toolbar.setSubtrees.done(function (subtrees) {
|
||||
menuModel.set('subtrees', subtrees);
|
||||
localStorage.setItem('Drupal.toolbar.subtrees', JSON.stringify(subtrees));
|
||||
var theme = drupalSettings.ajaxPageState.theme;
|
||||
localStorage.setItem('Drupal.toolbar.subtrees.' + theme, JSON.stringify(subtrees));
|
||||
// Indicate on the toolbarModel that subtrees are now loaded.
|
||||
model.set('areSubtreesLoaded', true);
|
||||
});
|
||||
|
@ -233,4 +234,15 @@
|
|||
'</div></div>';
|
||||
};
|
||||
|
||||
/**
|
||||
* Ajax command to set the toolbar subtrees.
|
||||
*
|
||||
* @param {Drupal.Ajax} ajax
|
||||
* @param {object} response
|
||||
* @param {number} [status]
|
||||
*/
|
||||
Drupal.AjaxCommands.prototype.setToolbarSubtrees = function (ajax, response, status) {
|
||||
Drupal.toolbar.setSubtrees.resolve(response.subtrees);
|
||||
};
|
||||
|
||||
}(jQuery, Drupal, drupalSettings));
|
||||
|
|
|
@ -249,7 +249,8 @@
|
|||
},
|
||||
|
||||
/**
|
||||
* Calls the endpoint URI that will return rendered subtrees with JSONP.
|
||||
* Calls the endpoint URI that builds an AJAX command with the rendered
|
||||
* subtrees.
|
||||
*
|
||||
* The rendered admin menu subtrees HTML is cached on the client in
|
||||
* localStorage until the cache of the admin menu subtrees on the server-
|
||||
|
@ -267,10 +268,10 @@
|
|||
// (3) The orientation of the tray is vertical.
|
||||
if (!this.model.get('areSubtreesLoaded') && typeof $activeTab.data('drupal-subtrees') !== 'undefined' && orientation === 'vertical') {
|
||||
var subtreesHash = drupalSettings.toolbar.subtreesHash;
|
||||
var langcode = drupalSettings.toolbar.langcode;
|
||||
var endpoint = Drupal.url('toolbar/subtrees/' + subtreesHash + '/' + langcode);
|
||||
var cachedSubtreesHash = localStorage.getItem('Drupal.toolbar.subtreesHash');
|
||||
var cachedSubtrees = JSON.parse(localStorage.getItem('Drupal.toolbar.subtrees'));
|
||||
var theme = drupalSettings.ajaxPageState.theme;
|
||||
var endpoint = Drupal.url('toolbar/subtrees/' + subtreesHash);
|
||||
var cachedSubtreesHash = localStorage.getItem('Drupal.toolbar.subtreesHash.' + theme);
|
||||
var cachedSubtrees = JSON.parse(localStorage.getItem('Drupal.toolbar.subtrees.' + theme));
|
||||
var isVertical = this.model.get('orientation') === 'vertical';
|
||||
// If we have the subtrees in localStorage and the subtree hash has not
|
||||
// changed, then use the cached data.
|
||||
|
@ -281,13 +282,13 @@
|
|||
// toolbar is vertical.
|
||||
else if (isVertical) {
|
||||
// Remove the cached menu information.
|
||||
localStorage.removeItem('Drupal.toolbar.subtreesHash');
|
||||
localStorage.removeItem('Drupal.toolbar.subtrees');
|
||||
// The response from the server will call the resolve method of the
|
||||
localStorage.removeItem('Drupal.toolbar.subtreesHash.' + theme);
|
||||
localStorage.removeItem('Drupal.toolbar.subtrees.' + theme);
|
||||
// The AJAX response's command will trigger the resolve method of the
|
||||
// Drupal.toolbar.setSubtrees Promise.
|
||||
$.ajax(endpoint);
|
||||
Drupal.ajax({url: endpoint}).execute();
|
||||
// Cache the hash for the subtrees locally.
|
||||
localStorage.setItem('Drupal.toolbar.subtreesHash', subtreesHash);
|
||||
localStorage.setItem('Drupal.toolbar.subtreesHash.' + theme, subtreesHash);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
44
core/modules/toolbar/src/Ajax/SetSubtreesCommand.php
Normal file
44
core/modules/toolbar/src/Ajax/SetSubtreesCommand.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\toolbar\Ajax\SetSubtreesCommand.
|
||||
*/
|
||||
|
||||
namespace Drupal\toolbar\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\CommandInterface;
|
||||
|
||||
/**
|
||||
* Defines an AJAX command that sets the toolbar subtrees.
|
||||
*/
|
||||
class SetSubtreesCommand implements CommandInterface {
|
||||
|
||||
/**
|
||||
* The toolbar subtrees.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $subtrees;
|
||||
|
||||
/**
|
||||
* Constructs a SetSubtreesCommand object.
|
||||
*
|
||||
* @param array $subtrees
|
||||
* The toolbar subtrees that will be set.
|
||||
*/
|
||||
public function __construct($subtrees) {
|
||||
$this->subtrees = $subtrees;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function render() {
|
||||
return [
|
||||
'command' => 'setToolbarSubtrees',
|
||||
'subtrees' => array_map('strval', $this->subtrees),
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -8,8 +8,9 @@
|
|||
namespace Drupal\toolbar\Controller;
|
||||
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Drupal\toolbar\Ajax\SetSubtreesCommand;
|
||||
|
||||
/**
|
||||
* Defines a controller for the toolbar module.
|
||||
|
@ -17,14 +18,14 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
|||
class ToolbarController extends ControllerBase {
|
||||
|
||||
/**
|
||||
* Returns the rendered subtree of each top-level toolbar link.
|
||||
* Returns an AJAX response to render the toolbar subtrees.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
* @return \Drupal\Core\Ajax\AjaxResponse
|
||||
*/
|
||||
public function subtreesJsonp() {
|
||||
$subtrees = toolbar_get_rendered_subtrees();
|
||||
$response = new JsonResponse($subtrees);
|
||||
$response->setCallback('Drupal.toolbar.setSubtrees.resolve');
|
||||
public function subtreesAjax() {
|
||||
list($subtrees, $cacheability) = toolbar_get_rendered_subtrees();
|
||||
$response = new AjaxResponse();
|
||||
$response->addCommand(new SetSubtreesCommand($subtrees));
|
||||
|
||||
// The Expires HTTP header is the heart of the client-side HTTP caching. The
|
||||
// additional server-side page cache only takes effect when the client
|
||||
|
@ -46,14 +47,12 @@ class ToolbarController extends ControllerBase {
|
|||
*
|
||||
* @param string $hash
|
||||
* The hash of the toolbar subtrees.
|
||||
* @param string $langcode
|
||||
* The langcode of the requested site, NULL if none given.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
public function checkSubTreeAccess($hash, $langcode) {
|
||||
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && $hash == _toolbar_get_subtrees_hash($langcode))->cachePerPermissions();
|
||||
public function checkSubTreeAccess($hash) {
|
||||
return AccessResult::allowedIf($this->currentUser()->hasPermission('access toolbar') && $hash == _toolbar_get_subtrees_hash()[0])->cachePerPermissions();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Drupal\toolbar\Tests;
|
|||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\user\RoleInterface;
|
||||
|
@ -118,7 +119,7 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
// Enable a module.
|
||||
$edit = array();
|
||||
$edit['modules[Core][taxonomy][enable]'] = TRUE;
|
||||
$this->drupalPostForm('admin/modules', $edit, t('Save configuration'));
|
||||
$this->drupalPostForm('admin/modules', $edit, t('Install'));
|
||||
$this->rebuildContainer();
|
||||
|
||||
// Assert that the subtrees hash has been altered because the subtrees
|
||||
|
@ -209,98 +210,11 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
$this->assertEqual($admin_user_2_hash, $new_subtree_hash, 'The user-specific subtree menu hash has not been updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all toolbar cache entries for a user are cleared with a cache
|
||||
* tag for that user, i.e. cache entries for all languages for that user.
|
||||
*/
|
||||
function testCacheClearByCacheTag() {
|
||||
// Test that the toolbar admin menu subtrees cache is invalidated for a user
|
||||
// across multiple languages.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$toolbarCache = $this->container->get('cache.toolbar');
|
||||
$admin_user_id = $this->adminUser->id();
|
||||
$admin_user_2_id = $this->adminUser2->id();
|
||||
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser against the language "en".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . 'en');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "en".');
|
||||
|
||||
// Assert that no toolbar cache exists for adminUser against the
|
||||
// language "fr".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . 'fr');
|
||||
$this->assertFalse($cache, 'No toolbar cache exists for admin_user against the language "fr".');
|
||||
|
||||
// Install a second language.
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'fr',
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, 'Add language');
|
||||
|
||||
// Request a page in 'fr' to update the cache.
|
||||
$this->drupalGet('fr/test-page');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser against the language "fr".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . 'fr');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "fr".');
|
||||
|
||||
// Log in the adminUser2 user. We will use this user as a control to
|
||||
// verify that clearing a cache tag for adminUser does not clear the cache
|
||||
// for adminUser2.
|
||||
$this->drupalLogin($this->adminUser2);
|
||||
|
||||
// Request a page in 'en' to create the cache.
|
||||
$this->drupalGet('test-page');
|
||||
$this->assertResponse(200);
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser2 against the language "en".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'en');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".');
|
||||
|
||||
// Request a page in 'fr' to create the cache.
|
||||
$this->drupalGet('fr/test-page');
|
||||
$this->assertResponse(200);
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser against the language "fr".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'fr');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".');
|
||||
|
||||
// Log in the admin user and clear the caches for this user using a tag.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
Cache::invalidateTags(array('user:' . $admin_user_id));
|
||||
|
||||
// Assert that no toolbar cache exists for adminUser against the
|
||||
// language "en".
|
||||
$cache = $toolbarCache->get($admin_user_id . ':' . 'en');
|
||||
$this->assertFalse($cache, 'No toolbar cache exists for admin_user against the language "en".');
|
||||
|
||||
// Assert that no toolbar cache exists for adminUser against the
|
||||
// language "fr".
|
||||
$cache = $toolbarCache->get($admin_user_id . ':' . 'fr');
|
||||
$this->assertFalse($cache, 'No toolbar cache exists for admin_user against the language "fr".');
|
||||
|
||||
// Log in adminUser2 and verify that this user's caches still exist.
|
||||
$this->drupalLogin($this->adminUser2);
|
||||
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser2 against the language "en".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'en');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".');
|
||||
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser2 against the language "fr".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_2_id . ':' . 'fr');
|
||||
$this->assertEqual(in_array('user:' . $admin_user_2_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that changes to a user account by another user clears the changed
|
||||
* account's toolbar cached, not the user's who took the action.
|
||||
*/
|
||||
function testNonCurrentUserAccountUpdates() {
|
||||
$toolbarCache = $this->container->get('cache.toolbar');
|
||||
$admin_user_id = $this->adminUser->id();
|
||||
$admin_user_2_id = $this->adminUser2->id();
|
||||
$this->hash = $this->getSubtreesHash();
|
||||
|
@ -337,9 +251,7 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
* Tests that toolbar cache is cleared when string translations are made.
|
||||
*/
|
||||
function testLocaleTranslationSubtreesHashCacheClear() {
|
||||
$toolbarCache = $this->container->get('cache.toolbar');
|
||||
$admin_user = $this->adminUser;
|
||||
$admin_user_id = $this->adminUser->id();
|
||||
// User to translate and delete string.
|
||||
$translate_user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
|
||||
|
||||
|
@ -373,11 +285,6 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
$this->drupalGet($langcode . '/test-page');
|
||||
$this->assertResponse(200);
|
||||
|
||||
// Assert that a cache tag in the toolbar cache under the key "user" exists
|
||||
// for adminUser against the language "xx".
|
||||
$cache = $toolbarCache->get('toolbar_' . $admin_user_id . ':' . $langcode);
|
||||
$this->assertEqual(in_array('user:' . $admin_user_id, $cache->tags), 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "xx".');
|
||||
|
||||
// Get a baseline hash for the admin menu subtrees before translating one
|
||||
// of the menu link items.
|
||||
$original_subtree_hash = $this->getSubtreesHash();
|
||||
|
@ -425,7 +332,7 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests that the 'toolbar/subtrees/{hash}' is reachable.
|
||||
* Tests that the 'toolbar/subtrees/{hash}' is reachable and correct.
|
||||
*/
|
||||
function testSubtreesJsonRequest() {
|
||||
$admin_user = $this->adminUser;
|
||||
|
@ -433,30 +340,10 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
// Request a new page to refresh the drupalSettings object.
|
||||
$subtrees_hash = $this->getSubtreesHash();
|
||||
|
||||
$this->drupalGetJSON('toolbar/subtrees/' . $subtrees_hash);
|
||||
$this->assertResponse('200');
|
||||
|
||||
// Test that the subtrees hash changes with a different language code and
|
||||
// that JSON is returned when a language code is specified.
|
||||
// Create a new language with the langcode 'xx'.
|
||||
$langcode = 'xx';
|
||||
// The English name for the language. This will be translated.
|
||||
$name = $this->randomMachineName(16);
|
||||
$edit = array(
|
||||
'predefined_langcode' => 'custom',
|
||||
'langcode' => $langcode,
|
||||
'label' => $name,
|
||||
'direction' => LanguageInterface::DIRECTION_LTR,
|
||||
);
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add custom language'));
|
||||
|
||||
// Get a page with the new language langcode in the URL.
|
||||
$this->drupalGet('xx/test-page');
|
||||
// Request a new page to refresh the drupalSettings object.
|
||||
$subtrees_hash = $this->getSubtreesHash();
|
||||
|
||||
$this->drupalGetJSON('toolbar/subtrees/' . $subtrees_hash . '/' . $langcode);
|
||||
$ajax_result = $this->drupalGetAjax('toolbar/subtrees/' . $subtrees_hash);
|
||||
$this->assertResponse('200');
|
||||
$this->assertEqual($ajax_result[0]['command'], 'setToolbarSubtrees', 'Subtrees response uses the correct command.');
|
||||
$this->assertEqual(array_keys($ajax_result[0]['subtrees']), ['system-admin_content', 'system-admin_structure', 'system-themes_page', 'system-modules_list', 'system-admin_config', 'entity-user-collection', 'front'], 'Correct subtrees returned.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -493,6 +380,26 @@ class ToolbarAdminMenuTest extends WebTestBase {
|
|||
$this->assertTrue($back_link);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that external links added to the menu appear in the toolbar.
|
||||
*/
|
||||
public function testExternalLink() {
|
||||
$edit = [
|
||||
'title[0][value]' => 'External URL',
|
||||
'link[0][uri]' => 'http://example.org',
|
||||
'menu_parent' => 'admin:system.admin',
|
||||
];
|
||||
$this->drupalPostForm('admin/structure/menu/manage/admin/add', $edit, 'Save');
|
||||
|
||||
// Assert that the new menu link is shown on the menu link listing.
|
||||
$this->drupalGet('admin/structure/menu/manage/admin');
|
||||
$this->assertText('External URL');
|
||||
|
||||
// Assert that the new menu link is shown in the toolbar on a regular page.
|
||||
$this->drupalGet(Url::fromRoute('<front>'));
|
||||
$this->assertText('External URL');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the hash value from the admin menu subtrees route path.
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
toolbar.narrow:
|
||||
label: narrow
|
||||
mediaQuery: 'only screen and (min-width: 16.5em)'
|
||||
weight: 2
|
||||
weight: 0
|
||||
multipliers:
|
||||
- 1x
|
||||
toolbar.standard:
|
||||
|
@ -13,6 +13,6 @@ toolbar.standard:
|
|||
toolbar.wide:
|
||||
label: wide
|
||||
mediaQuery: 'only screen and (min-width: 61em)'
|
||||
weight: 0
|
||||
weight: 2
|
||||
multipliers:
|
||||
- 1x
|
||||
|
|
|
@ -22,6 +22,7 @@ toolbar:
|
|||
- core/jquery
|
||||
- core/drupal
|
||||
- core/drupalSettings
|
||||
- core/drupal.ajax
|
||||
- core/drupal.announce
|
||||
- core/backbone
|
||||
- core/matchmedia
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
use Drupal\Core\Cache\CacheableMetadata;
|
||||
use Drupal\Core\Menu\MenuTreeParameters;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
|
@ -13,7 +14,6 @@ use Drupal\Core\Template\Attribute;
|
|||
use Drupal\Component\Datetime\DateTimePlus;
|
||||
use Drupal\Component\Utility\Crypt;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\user\Entity\Role;
|
||||
use Drupal\Core\Url;
|
||||
|
||||
/**
|
||||
|
@ -158,10 +158,9 @@ function toolbar_toolbar() {
|
|||
// toolbar_subtrees route. We provide the JavaScript requesting that JSONP
|
||||
// script here with the hash parameter that is needed for that route.
|
||||
// @see toolbar_subtrees_jsonp()
|
||||
$langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
|
||||
list($hash, $hash_cacheability) = _toolbar_get_subtrees_hash();
|
||||
$subtrees_attached['drupalSettings']['toolbar'] = [
|
||||
'subtreesHash' => _toolbar_get_subtrees_hash($langcode),
|
||||
'langcode' => $langcode,
|
||||
'subtreesHash' => $hash,
|
||||
];
|
||||
|
||||
// The administration element has a link that is themed to correspond to
|
||||
|
@ -198,6 +197,7 @@ function toolbar_toolbar() {
|
|||
),
|
||||
'#weight' => -15,
|
||||
);
|
||||
$hash_cacheability->applyTo($items['administration']);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
@ -215,10 +215,13 @@ function toolbar_toolbar() {
|
|||
*/
|
||||
function toolbar_prerender_toolbar_administration_tray(array $element) {
|
||||
$menu_tree = \Drupal::service('toolbar.menu_tree');
|
||||
// Render the top-level administration menu links.
|
||||
// Load the administrative menu. The first level is the "Administration" link.
|
||||
// In order to load the children of that link, start and end on the second
|
||||
// level.
|
||||
$parameters = new MenuTreeParameters();
|
||||
$parameters->setRoot('system.admin')->excludeRoot()->setTopLevelOnly()->onlyEnabledLinks();
|
||||
$tree = $menu_tree->load(NULL, $parameters);
|
||||
$parameters->setMinDepth(2)->setMaxDepth(2)->onlyEnabledLinks();
|
||||
// @todo Make the menu configurable in https://www.drupal.org/node/1869638.
|
||||
$tree = $menu_tree->load('admin', $parameters);
|
||||
$manipulators = array(
|
||||
array('callable' => 'menu.default_tree_manipulators:checkAccess'),
|
||||
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
|
||||
|
@ -248,7 +251,7 @@ function toolbar_menu_navigation_links(array $tree) {
|
|||
// and behaviors to the menu links.
|
||||
$link = $element->link;
|
||||
$url = $link->getUrlObject();
|
||||
if ($url->isExternal()) {
|
||||
if (!$url->isRouted()) {
|
||||
// This is an unusual case, so just get a distinct, safe string.
|
||||
$id = substr(Crypt::hashBase64($url->getUri()), 0, 16);
|
||||
}
|
||||
|
@ -269,12 +272,38 @@ function toolbar_menu_navigation_links(array $tree) {
|
|||
|
||||
/**
|
||||
* Returns the rendered subtree of each top-level toolbar link.
|
||||
*
|
||||
* @return array
|
||||
* An array with the following key-value pairs:
|
||||
* - 'subtrees': the rendered subtrees
|
||||
* - 'cacheability: the associated cacheability.
|
||||
*/
|
||||
function toolbar_get_rendered_subtrees() {
|
||||
$data = [
|
||||
'#pre_render' => ['_toolbar_do_get_rendered_subtrees'],
|
||||
'#cache' => [
|
||||
'keys' => [
|
||||
'toolbar_rendered_subtrees',
|
||||
],
|
||||
],
|
||||
'#cache_properties' => ['#subtrees'],
|
||||
];
|
||||
\Drupal::service('renderer')->renderPlain($data);
|
||||
return [$data['#subtrees'], CacheableMetadata::createFromRenderArray($data)];
|
||||
}
|
||||
|
||||
/**
|
||||
* #pre_render callback for toolbar_get_rendered_subtrees().
|
||||
*/
|
||||
function _toolbar_do_get_rendered_subtrees(array $data) {
|
||||
$menu_tree = \Drupal::service('toolbar.menu_tree');
|
||||
// Load the administration menu. The first level is the "Administration" link.
|
||||
// In order to load the children of that link and the subsequent two levels,
|
||||
// start at the second level and end at the fourth.
|
||||
$parameters = new MenuTreeParameters();
|
||||
$parameters->setRoot('system.admin')->excludeRoot()->setMaxDepth(3)->onlyEnabledLinks();
|
||||
$tree = $menu_tree->load(NULL, $parameters);
|
||||
$parameters->setMinDepth(2)->setMaxDepth(4)->onlyEnabledLinks();
|
||||
// @todo Make the menu configurable in https://www.drupal.org/node/1869638.
|
||||
$tree = $menu_tree->load('admin', $parameters);
|
||||
$manipulators = array(
|
||||
array('callable' => 'menu.default_tree_manipulators:checkAccess'),
|
||||
array('callable' => 'menu.default_tree_manipulators:generateIndexAndSort'),
|
||||
|
@ -282,65 +311,42 @@ function toolbar_get_rendered_subtrees() {
|
|||
);
|
||||
$tree = $menu_tree->transform($tree, $manipulators);
|
||||
$subtrees = array();
|
||||
// Calculated the combined cacheability of all subtrees.
|
||||
$cacheability = new CacheableMetadata();
|
||||
foreach ($tree as $element) {
|
||||
/** @var \Drupal\Core\Menu\MenuLinkInterface $link */
|
||||
$link = $element->link;
|
||||
if ($element->subtree) {
|
||||
$subtree = $menu_tree->build($element->subtree);
|
||||
$output = \Drupal::service('renderer')->renderPlain($subtree);
|
||||
$cacheability = $cacheability->merge(CacheableMetadata::createFromRenderArray($subtree));
|
||||
}
|
||||
else {
|
||||
$output = '';
|
||||
}
|
||||
// Many routes have dots as route name, while some special ones like <front>
|
||||
// have <> characters in them.
|
||||
$id = str_replace(array('.', '<', '>'), array('-', '', '' ), $link->getUrlObject()->getRouteName());
|
||||
$url = $link->getUrlObject();
|
||||
$id = str_replace(array('.', '<', '>'), array('-', '', '' ), $url->isRouted() ? $url->getRouteName() : $url->getUri());
|
||||
|
||||
$subtrees[$id] = $output;
|
||||
}
|
||||
return $subtrees;
|
||||
|
||||
// Store the subtrees, along with the cacheability metadata.
|
||||
$cacheability->applyTo($data);
|
||||
$data['#subtrees'] = $subtrees;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash of the per-user rendered toolbar subtrees.
|
||||
*
|
||||
* @param string $langcode
|
||||
* The langcode of the current request.
|
||||
*
|
||||
* @return string
|
||||
* The hash of the admin_menu subtrees.
|
||||
*/
|
||||
function _toolbar_get_subtrees_hash($langcode) {
|
||||
$uid = \Drupal::currentUser()->id();
|
||||
$cid = _toolbar_get_user_cid($uid, $langcode);
|
||||
if ($cache = \Drupal::cache('toolbar')->get($cid)) {
|
||||
$hash = $cache->data;
|
||||
}
|
||||
else {
|
||||
$subtrees = toolbar_get_rendered_subtrees();
|
||||
$hash = Crypt::hashBase64(serialize($subtrees));
|
||||
// Cache using a tag 'user' so that we can invalidate all user-specific
|
||||
// caches later, based on the user's ID regardless of language.
|
||||
// Clear the cache when the 'locale' tag is deleted. This ensures a fresh
|
||||
// subtrees rendering when string translations are made.
|
||||
$role_list_cache_tags = \Drupal::entityManager()->getDefinition('user_role')->getListCacheTags();
|
||||
\Drupal::cache('toolbar')->set($cid, $hash, Cache::PERMANENT, Cache::mergeTags(array('user:' . $uid, 'locale', 'config:system.menu.admin'), $role_list_cache_tags));
|
||||
}
|
||||
return $hash;
|
||||
function _toolbar_get_subtrees_hash() {
|
||||
list($subtrees, $cacheability) = toolbar_get_rendered_subtrees();
|
||||
$hash = Crypt::hashBase64(serialize($subtrees));
|
||||
return [$hash, $cacheability];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cache ID from the user and language IDs.
|
||||
*
|
||||
* @param int $uid
|
||||
* A user ID.
|
||||
* @param string $langcode
|
||||
* The langcode of the current request.
|
||||
*
|
||||
* @return string
|
||||
* A unique cache ID for the user.
|
||||
*/
|
||||
function _toolbar_get_user_cid($uid, $langcode) {
|
||||
return 'toolbar_' . $uid . ':' . $langcode;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
toolbar.subtrees:
|
||||
path: '/toolbar/subtrees/{hash}/{langcode}'
|
||||
path: '/toolbar/subtrees/{hash}'
|
||||
defaults:
|
||||
_controller: '\Drupal\toolbar\Controller\ToolbarController::subtreesJsonp'
|
||||
langcode: null
|
||||
_controller: '\Drupal\toolbar\Controller\ToolbarController::subtreesAjax'
|
||||
options:
|
||||
_theme: ajax_base_page
|
||||
requirements:
|
||||
_custom_access: '\Drupal\toolbar\Controller\ToolbarController::checkSubTreeAccess'
|
||||
|
|
Reference in a new issue