core/modules/toolbar/js/toolbar.js | 35 ++++++++------- .../lib/Drupal/toolbar/Access/SubtreeAccess.php | 2 +- .../Drupal/toolbar/Tests/ToolbarAdminMenuTest.php | 45 +++++++++----------- core/modules/toolbar/toolbar.module | 20 ++++----- 4 files changed, 49 insertions(+), 53 deletions(-) diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js index 29b2195..bfcd891 100644 --- a/core/modules/toolbar/js/toolbar.js +++ b/core/modules/toolbar/js/toolbar.js @@ -89,12 +89,13 @@ Drupal.behaviors.toolbar = { } } - // Trigger an initial attempt to load menu sub-items. This first attempt + // Trigger an initial attempt to load menu subitems. This first attempt // is made after the media query handlers have had an opportunity to - // process. The toolbar starts in the vertical position by default, unless - // the viewport is wide enough to accomodate a horizontal orientation. - // Thus we give the Toolbar a chance to determine if it should be set - // to horizontal before attempting to load menu subtrees. + // process. The toolbar starts in the vertical orientation by default, + // unless the viewport is wide enough to accomodate a horizontal + // orientation. Thus we give the Toolbar a chance to determine if it + // should be set to horizontal orientation before attempting to load menu + // subtrees. Drupal.toolbar.views.toolbarVisualView.loadSubtrees(); $(document) @@ -328,14 +329,12 @@ Drupal.toolbar = { /** * {@inheritdoc} */ - render: function (model, value) { + render: function () { this.updateTabs(); this.updateTrayOrientation(); this.updateBarAttributes(); // Load the subtrees if the toolbar tray is in a vertical orientation. - // There is no other attribute in the model with the value of vertical - // that could be confused with the orientation attribute. - if (value && value === 'vertical') { + if (this.model.changed.orientation === 'vertical') { this.loadSubtrees(); } // Trigger a recalculation of viewport displacing elements. Use setTimeout @@ -510,14 +509,14 @@ Drupal.toolbar = { */ loadSubtrees: function () { if (!this.model.get('areSubtreesLoaded')) { - var endpoint = drupalSettings.toolbar.subtreesPath; - var cachedEndpoint = localStorage.getItem('Drupal.toolbar.subtreesPath'); + var subtreesHash = drupalSettings.toolbar.subtreesHash; + var endpoint = Drupal.url('toolbar/subtrees/' + subtreesHash); + var cachedSubtreesHash = localStorage.getItem('Drupal.toolbar.subtreesHash'); var cachedSubtrees = JSON.parse(localStorage.getItem('Drupal.toolbar.subtrees')); var isVertical = this.model.get('orientation') === 'vertical'; - // If we have the subtrees in localStorage and the endpoint url -- - // including the hash of the subtrees -- has not changed, then use - // the cached data. - if (isVertical && endpoint === cachedEndpoint && cachedSubtrees) { + // If we have the subtrees in localStorage and the subtree hash has not + // changed, then use the cached data. + if (isVertical && subtreesHash === cachedSubtreesHash && cachedSubtrees) { Drupal.toolbar.setSubtrees.resolve(cachedSubtrees); this.model.set('areSubtreesLoaded', true); } @@ -525,13 +524,13 @@ Drupal.toolbar = { // toolbar is vertical. else if (isVertical) { // Remove the cached menu information. - localStorage.removeItem('Drupal.toolbar.subtreesPath'); + localStorage.removeItem('Drupal.toolbar.subtreesHash'); localStorage.removeItem('Drupal.toolbar.subtrees'); // The response from the server will call the resolve method of the // Drupal.toolbar.setSubtrees Promise. $.ajax(endpoint); - // Cached the endpoint to the subtrees locally. - localStorage.setItem('Drupal.toolbar.subtreesPath', endpoint); + // Cache the hash for the subtrees locally. + localStorage.setItem('Drupal.toolbar.subtreesHash', subtreesHash); this.model.set('areSubtreesLoaded', true); } } diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Access/SubtreeAccess.php b/core/modules/toolbar/lib/Drupal/toolbar/Access/SubtreeAccess.php index 41813c0..131bc6a 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Access/SubtreeAccess.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Access/SubtreeAccess.php @@ -28,7 +28,7 @@ public function appliesTo() { */ public function access(Route $route, Request $request) { $hash = $request->get('hash'); - return (user_access('access toolbar') && ($hash == _toolbar_get_subtree_hash())) ? static::ALLOW : static::DENY; + return (user_access('access toolbar') && ($hash == _toolbar_get_subtrees_hash())) ? static::ALLOW : static::DENY; } } diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php index 273c7c0..1c28ec7 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php @@ -10,7 +10,6 @@ use Drupal\simpletest\WebTestBase; /** - * * Tests the caching of the admin menu subtree items. * * The cache of the admin menu subtree items will be invalidated if the @@ -100,10 +99,11 @@ function setUp() { } /** - * Exercises the toolbar_modules_enabled() and toolbar_modules_disabled() hook + * Tests the toolbar_modules_enabled() and toolbar_modules_disabled() hook * implementations. */ function testModuleStatusChangeSubtreesHashCacheClear() { + // Disable a module. $edit = array(); $edit['modules[Core][taxonomy][enable]'] = FALSE; $this->drupalPost('admin/modules', $edit, t('Save configuration')); @@ -113,7 +113,7 @@ function testModuleStatusChangeSubtreesHashCacheClear() { // structure changed. $this->assertDifferentHash(); - // Test enabling a module. + // Enable a module. $edit = array(); $edit['modules[Core][taxonomy][enable]'] = TRUE; $this->drupalPost('admin/modules', $edit, t('Save configuration')); @@ -125,7 +125,7 @@ function testModuleStatusChangeSubtreesHashCacheClear() { } /** - * Exercises toolbar_menu_link_update() hook implementation. + * Tests toolbar_menu_link_update() hook implementation. */ function testMenuLinkUpdateSubtreesHashCacheClear() { // Get subtree items for the admin menu. @@ -175,7 +175,7 @@ function testUserRoleUpdateSubtreesHashCacheClear() { // structure changed. $this->assertDifferentHash(); - // Test that a user role change only affects a single user. + // Test that assigning a user an extra role only affects that single user. // Get the hash for a second user. $this->drupalLogin($this->admin_user_2); $this->drupalGet('test-page'); @@ -222,8 +222,8 @@ function testUserRoleUpdateSubtreesHashCacheClear() { } /** - * Tests that the toolbar user cache is cleared with a cache tag for all - * languages that have cached admin menu subtrees. + * 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 @@ -238,7 +238,7 @@ function testCacheClearByCacheTag() { $cache = $toolbarCache->get($admin_user_id . ':' . 'en'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "en".'); - // Asert that no toolbar cache exists for admin_user against the + // Assert that no toolbar cache exists for admin_user 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".'); @@ -253,7 +253,7 @@ function testCacheClearByCacheTag() { $this->drupalGet('fr/test-page'); $this->assertResponse(200); - // Asert that a cache tag in the toolbar cache under the key "user" exists + // Assert that a cache tag in the toolbar cache under the key "user" exists // for admin_user against the language "fr". $cache = $toolbarCache->get($admin_user_id . ':' . 'fr'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user against the language "fr".'); @@ -266,31 +266,29 @@ function testCacheClearByCacheTag() { // Request a page in 'en' to create the cache. $this->drupalGet('test-page'); $this->assertResponse(200); - // Asert that a cache tag in the toolbar cache under the key "user" exists - // for admin_user against the language "en". + // Assert that a cache tag in the toolbar cache under the key "user" exists + // for admin_user_2 against the language "en". $cache = $toolbarCache->get($admin_user_2_id . ':' . 'en'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); - // Request a page in 'en' to create the cache. + // Request a page in 'fr' to create the cache. $this->drupalGet('fr/test-page'); $this->assertResponse(200); - // Asert that a cache tag in the toolbar cache under the key "user" exists + // Assert that a cache tag in the toolbar cache under the key "user" exists // for admin_user against the language "fr". $cache = $toolbarCache->get($admin_user_2_id . ':' . 'fr'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); // Log in admin_user and clear the caches for this user using a tag. $this->drupalLogin($this->admin_user); - - // Delete the toolbar cache for the admin_user based on a tag. $toolbarCache->deleteTags(array('user' => array($admin_user_id))); - // Asert that no toolbar cache exists for admin_user against the + // Assert that no toolbar cache exists for admin_user 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".'); - // Asert that no toolbar cache exists for admin_user against the + // Assert that no toolbar cache exists for admin_user 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".'); @@ -298,12 +296,12 @@ function testCacheClearByCacheTag() { // Log in admin_user_2 and verify that this user's caches still exist. $this->drupalLogin($this->admin_user_2); - // Asert that a cache tag in the toolbar cache under the key "user" exists + // Assert that a cache tag in the toolbar cache under the key "user" exists // for admin_user_2 against the language "en". $cache = $toolbarCache->get($admin_user_2_id . ':' . 'en'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "en".'); - // Asert that a cache tag in the toolbar cache under the key "user" exists + // Assert that a cache tag in the toolbar cache under the key "user" exists // for admin_user_2 against the language "fr". $cache = $toolbarCache->get($admin_user_2_id . ':' . 'fr'); $this->assertEqual($cache->tags[0], 'user:' . $admin_user_2_id, 'A cache tag in the toolbar cache under the key "user" exists for admin_user_2 against the language "fr".'); @@ -350,16 +348,15 @@ function testNonCurrentUserAccountUpdates() { /** * Get the hash value from the admin menu subtrees route path. * - * @return String + * @return string * The hash value from the admin menu subtrees route path. */ private function getSubtreesHash() { $settings = $this->drupalGetSettings(); // The toolbar module defines a route '/toolbar/subtrees/{hash}' that - // returns JSON for the rendered subtrees. This path is provided to the - // client in drupalSettings. To get just the hash value, remove the - // '/toolbar/subtrees/' portion of the path. - return substr($settings['toolbar']['subtreesPath'], 18); + // returns JSON for the rendered subtrees. This hash is provided to the + // client in drupalSettings. + return $settings['toolbar']['subtreesHash']; } /** diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 11a4962..f3d7edc 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -440,14 +440,14 @@ function toolbar_toolbar() { ); // To conserve bandwidth, we only include the top-level links in the HTML. - // The subtrees are fetched through a JSONP script. Here we - // add that JSONP script URL. We add it as a path because it is not a file - // available via a stream wrapper. + // The subtrees are fetched through a JSONP script that is generated at the + // 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() $menu['toolbar_administration']['#attached']['js'][] = array( 'type' => 'setting', 'data' => array('toolbar' => array( - 'subtreesPath' => url('toolbar/subtrees/' . _toolbar_get_subtree_hash()), + 'subtreesHash' => _toolbar_get_subtrees_hash(), )), ); @@ -613,7 +613,7 @@ function toolbar_library_info() { * @return string * The hash of the admin_menu subtrees. */ -function _toolbar_get_subtree_hash() { +function _toolbar_get_subtrees_hash() { $uid = \Drupal::currentUser()->id(); $cid = _toolbar_get_user_cid($uid); if ($cache = cache('toolbar')->get($cid)) { @@ -622,8 +622,8 @@ function _toolbar_get_subtree_hash() { 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 uer's ID regardless of language. + // Cache using a tag 'user' so that we can invalidate all user-specific + // caches later, based on the user's ID regardless of language. cache('toolbar')->set($cid, $hash, CacheBackendInterface::CACHE_PERMANENT, array('user' => array($uid))); } return $hash; @@ -669,7 +669,7 @@ function toolbar_user_role_update(RoleInterface $role) { /** * Returns a cache ID from the user and language IDs. * - * @param string $uid + * @param int $uid * A user ID. * * @return string @@ -682,8 +682,8 @@ function _toolbar_get_user_cid($uid) { /** * Clears the Toolbar user cache. * - * @param string $uid - * (optional) The user ID to clear. + * @param int $uid + * (optional) The user ID whose toolbar cache entry to clear. */ function _toolbar_clear_user_cache($uid = NULL) { $cache = cache('toolbar');