diff --git a/core/modules/toolbar/js/views/ToolbarVisualView.js b/core/modules/toolbar/js/views/ToolbarVisualView.js index 2b6071ee47b6d52564ef28048beb3782af34211e..62908e0e552d96d69c61dc2ae66ce55b193cec7a 100644 --- a/core/modules/toolbar/js/views/ToolbarVisualView.js +++ b/core/modules/toolbar/js/views/ToolbarVisualView.js @@ -248,7 +248,8 @@ // (3) The orientation of the tray is vertical. if (!this.model.get('areSubtreesLoaded') && $activeTab.data('drupal-subtrees') !== undefined && orientation === 'vertical') { var subtreesHash = drupalSettings.toolbar.subtreesHash; - var endpoint = Drupal.url('toolbar/subtrees/' + 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 isVertical = this.model.get('orientation') === 'vertical'; diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php b/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php index d5fc878caf7583e6ea931a57a483c475026ad1d2..11d17b4c59fbe76fbf5f09ee07f683d0dedf8afb 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Controller/ToolbarController.php @@ -32,10 +32,19 @@ public function subtreesJsonp() { /** * Checks access for the subtree controller. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The current request. + * @param string $langcode + * The langcode of the requested site, NULL if none given. + * + * @return string + * Returns AccessInterface::ALLOW when access was granted, otherwise + * AccessInterface::DENY. */ - public function checkSubTreeAccess(Request $request) { + public function checkSubTreeAccess(Request $request, $langcode) { $hash = $request->get('hash'); - return ($this->currentUser()->hasPermission('access toolbar') && ($hash == _toolbar_get_subtrees_hash())) ? AccessInterface::ALLOW : AccessInterface::DENY; + return ($this->currentUser()->hasPermission('access toolbar') && ($hash == _toolbar_get_subtrees_hash($langcode))) ? AccessInterface::ALLOW : AccessInterface::DENY; } } diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php index 082a6a7e2facbafda62377be5e7da854d4784e5d..01f043e60ba0a6b1fbff11ba73c335285c1ebbbf 100644 --- a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php +++ b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarAdminMenuTest.php @@ -452,6 +452,55 @@ function testSubtreesJsonRequest() { $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->randomName(16); + $edit = array( + 'predefined_langcode' => 'custom', + 'langcode' => $langcode, + 'name' => $name, + 'direction' => '0', + ); + $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); + $this->assertResponse('200'); + } + + /** + * Test that subtrees hashes vary by the language of the page. + */ + function testLanguageSwitching() { + // Create a new language with the langcode 'xx'. + $langcode = 'xx'; + // The English name for the language. This will be translated. + $name = $this->randomName(16); + $edit = array( + 'predefined_langcode' => 'custom', + 'langcode' => $langcode, + 'name' => $name, + 'direction' => '0', + ); + $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'); + // Assert different hash. + $new_subtree_hash = $this->getSubtreesHash(); + + // Assert that the old admin menu subtree hash and the new admin menu + // subtree hash are different. + $this->assertTrue($new_subtree_hash, 'A valid hash value for the admin menu subtrees was created.'); + $this->assertNotEqual($this->hash, $new_subtree_hash, 'The user-specific subtree menu hash has been updated.'); } /** diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index 6e3e4e3e44140a871e300785501bff91398e0bd1..0f58cb277aef11911cb7d40bc4dbb35e15367401 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -378,10 +378,12 @@ 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()->id; $menu['toolbar_administration']['#attached']['js'][] = array( 'type' => 'setting', 'data' => array('toolbar' => array( - 'subtreesHash' => _toolbar_get_subtrees_hash(), + 'subtreesHash' => _toolbar_get_subtrees_hash($langcode), + 'langcode' => $langcode, )), ); @@ -503,12 +505,15 @@ function toolbar_get_rendered_subtrees() { /** * 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() { +function _toolbar_get_subtrees_hash($langcode) { $uid = \Drupal::currentUser()->id(); - $cid = _toolbar_get_user_cid($uid); + $cid = _toolbar_get_user_cid($uid, $langcode); if ($cache = \Drupal::cache('toolbar')->get($cid)) { $hash = $cache->data; } @@ -566,12 +571,14 @@ function toolbar_user_role_update(RoleInterface $role) { * * @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) { - return 'toolbar_' . $uid . ':' . \Drupal::languageManager()->getCurrentLanguage()->id; +function _toolbar_get_user_cid($uid, $langcode) { + return 'toolbar_' . $uid . ':' . $langcode; } /** diff --git a/core/modules/toolbar/toolbar.routing.yml b/core/modules/toolbar/toolbar.routing.yml index 6e2f2559bb31c2cb1222c8bfc0b197b61388d253..4cb014e53c56092f4144460a09061f0735ccedb1 100644 --- a/core/modules/toolbar/toolbar.routing.yml +++ b/core/modules/toolbar/toolbar.routing.yml @@ -1,6 +1,7 @@ toolbar.subtrees: - path: '/toolbar/subtrees/{hash}' + path: '/toolbar/subtrees/{hash}/{langcode}' defaults: _controller: '\Drupal\toolbar\Controller\ToolbarController::subtreesJsonp' + langcode: null requirements: _custom_access: '\Drupal\toolbar\Controller\ToolbarController::checkSubTreeAccess'