diff --git a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php index 51794b1be7efc8a93c3b636cc4b11776e9275bb3..1fe4719cab7b29cdd0894aa0c3ae20938eafda78 100644 --- a/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php +++ b/core/modules/toolbar/src/Tests/ToolbarAdminMenuTest.php @@ -10,6 +10,7 @@ use Drupal\Component\Serialization\Json; 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; @@ -384,6 +385,26 @@ public function testBackToSiteLink() { $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. * diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index ffd637af6de31ecbbb1639d8f12aa14c879c2efd..d837b176a115aaf6a57960870b2ac852e91287ca 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -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); } @@ -294,9 +297,13 @@ function 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'), @@ -319,7 +326,8 @@ function _toolbar_do_get_rendered_subtrees(array $data) { } // 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; } diff --git a/core/modules/views_ui/src/Tests/DisplayPathTest.php b/core/modules/views_ui/src/Tests/DisplayPathTest.php index cc6826fb2d1332e1a252386cdee13f3bfb316812..004b9f0451628b91004282ee37ef904314e11ecc 100644 --- a/core/modules/views_ui/src/Tests/DisplayPathTest.php +++ b/core/modules/views_ui/src/Tests/DisplayPathTest.php @@ -6,6 +6,8 @@ */ namespace Drupal\views_ui\Tests; +use Drupal\Core\Menu\MenuTreeParameters; +use Drupal\menu_link_content\Entity\MenuLinkContent; /** * Tests the UI of generic display path plugin. @@ -149,4 +151,71 @@ public function testMenuOptions() { $this->assertCacheContext('user.permissions'); } + /** + * Tests the regression in https://www.drupal.org/node/2532490. + */ + public function testDefaultMenuTabRegression() { + $this->container->get('module_installer')->install(['menu_ui', 'menu_link_content', 'toolbar', 'system']); + $admin_user = $this->drupalCreateUser([ + 'administer views', + 'administer blocks', + 'bypass node access', + 'access user profiles', + 'view all revisions', + 'administer permissions', + 'administer menu', + 'link to any page', + 'access toolbar', + ]); + $this->drupalLogin($admin_user); + + $edit = [ + 'title[0][value]' => 'Menu title', + 'link[0][uri]' => '/admin/foo', + 'menu_parent' => 'admin:system.admin' + ]; + $this->drupalPostForm('admin/structure/menu/manage/admin/add', $edit, t('Save')); + + $menu_items = \Drupal::entityManager()->getStorage('menu_link_content')->getQuery() + ->sort('id', 'DESC') + ->pager(1) + ->execute(); + $menu_item = end($menu_items); + /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link_content */ + $menu_link_content = MenuLinkContent::load($menu_item); + + $edit = []; + $edit['label'] = $this->randomMachineName(16); + $view_id = $edit['id'] = strtolower($this->randomMachineName(16)); + $edit['description'] = $this->randomMachineName(16); + $edit['page[create]'] = TRUE; + $edit['page[path]'] = 'admin/foo'; + + $this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit')); + + $parameters = new MenuTreeParameters(); + $parameters->addCondition('id', $menu_link_content->getPluginId()); + $result = \Drupal::menuTree()->load('admin', $parameters); + $plugin_definition = end($result)->link->getPluginDefinition(); + $this->assertEqual('view.' . $view_id . '.page_1', $plugin_definition['route_name']); + + $this->clickLink(t('No menu')); + + $this->drupalPostForm(NULL, [ + 'menu[type]' => 'default tab', + 'menu[title]' => 'Menu title', + ], t('Apply')); + + $this->assertText('Default tab options'); + + $this->drupalPostForm(NULL, [ + 'tab_options[type]' => 'normal', + 'tab_options[title]' => 'Parent title', + ], t('Apply')); + + $this->drupalPostForm(NULL, [], t('Save')); + // Assert that saving the view will not cause an exception. + $this->assertResponse(200); + } + }