diff --git a/core/includes/menu.inc b/core/includes/menu.inc index d578499..23aba4f 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -130,8 +130,8 @@ function menu_local_tasks($level = 0) { if (!\Drupal::request()->attributes->has('exception') && !empty($route_name)) { $manager = \Drupal::service('plugin.manager.menu.local_task'); $local_tasks = $manager->getTasksBuild($route_name); - foreach ($local_tasks as $level => $items) { - $data['tabs'][$level] = empty($data['tabs'][$level]) ? $items : array_merge($data['tabs'][$level], $items); + foreach ($local_tasks as $tab_level => $items) { + $data['tabs'][$tab_level] = empty($data['tabs'][$tab_level]) ? $items : array_merge($data['tabs'][$tab_level], $items); } } @@ -177,16 +177,6 @@ function menu_secondary_local_tasks() { } /** - * Returns the rendered local actions at the current level. - */ -function menu_get_local_actions() { - $links = menu_local_tasks(); - $route_name = Drupal::routeMatch()->getRouteName(); - $manager = \Drupal::service('plugin.manager.menu.local_action'); - return $manager->getActionsForRoute($route_name) + $links['actions']; -} - -/** * Returns the router path, or the path for a default local task's parent. */ function menu_tab_root_path() { diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 3b156a5..dfdcfaf 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1362,14 +1362,6 @@ function template_preprocess_page(&$variables) { $variables['is_front'] = FALSE; $variables['db_is_active'] = FALSE; } - if (!defined('MAINTENANCE_MODE')) { - $variables['action_links'] = menu_get_local_actions(); - $variables['tabs'] = menu_local_tabs(); - } - else { - $variables['action_links'] = array(); - $variables['tabs'] = array(); - } if ($node = \Drupal::routeMatch()->getParameter('node')) { $variables['node'] = $node; diff --git a/core/lib/Drupal/Core/Menu/LocalActionManager.php b/core/lib/Drupal/Core/Menu/LocalActionManager.php index db6acef..bdee9f3 100644 --- a/core/lib/Drupal/Core/Menu/LocalActionManager.php +++ b/core/lib/Drupal/Core/Menu/LocalActionManager.php @@ -190,10 +190,11 @@ public function getActionsForRoute($route_appears) { 'url' => Url::fromRoute($route_name, $route_parameters), 'localized_options' => $plugin->getOptions($this->routeMatch), ), - '#access' => $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account), + '#access' => $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE), '#weight' => $plugin->getWeight(), ); } + return $links; } diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php index 70b1102..826e549 100644 --- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php +++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php @@ -301,31 +301,28 @@ public function getTasksBuild($current_route_name) { $route_name = $child->getRouteName(); $route_parameters = $child->getRouteParameters($this->routeMatch); - // Find out whether the user has access to the task. - $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account); - if ($access) { - $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters); + $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters); - // The plugin may have been set active in getLocalTasksForRoute() if - // one of its child tabs is the active tab. - $active = $active || $child->getActive(); - // @todo It might make sense to use link render elements instead. + // The plugin may have been set active in getLocalTasksForRoute() if + // one of its child tabs is the active tab. + $active = $active || $child->getActive(); + // @todo It might make sense to use link render elements instead. - $link = array( - 'title' => $this->getTitle($child), - 'url' => Url::fromRoute($route_name, $route_parameters), - 'localized_options' => $child->getOptions($this->routeMatch), - ); - $build[$level][$plugin_id] = array( - '#theme' => 'menu_local_task', - '#link' => $link, - '#active' => $active, - '#weight' => $child->getWeight(), - '#access' => $access, - ); - } + $link = array( + 'title' => $this->getTitle($child), + 'url' => Url::fromRoute($route_name, $route_parameters), + 'localized_options' => $child->getOptions($this->routeMatch), + ); + $build[$level][$plugin_id] = array( + '#theme' => 'menu_local_task', + '#link' => $link, + '#active' => $active, + '#weight' => $child->getWeight(), + '#access' => $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE), + ); } } + return $build; } diff --git a/core/modules/aggregator/src/Tests/AggregatorTestBase.php b/core/modules/aggregator/src/Tests/AggregatorTestBase.php index 3bee7f4..7a45c33 100644 --- a/core/modules/aggregator/src/Tests/AggregatorTestBase.php +++ b/core/modules/aggregator/src/Tests/AggregatorTestBase.php @@ -28,7 +28,7 @@ * * @var array */ - public static $modules = array('node', 'aggregator', 'aggregator_test', 'views'); + public static $modules = ['block', 'node', 'aggregator', 'aggregator_test', 'views']; /** * {@inheritdoc} @@ -43,6 +43,7 @@ protected function setUp() { $this->adminUser = $this->drupalCreateUser(array('access administration pages', 'administer news feeds', 'access news feeds', 'create article content')); $this->drupalLogin($this->adminUser); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/block/src/Tests/BlockHiddenRegionTest.php b/core/modules/block/src/Tests/BlockHiddenRegionTest.php index 347cdaf..99d9deb 100644 --- a/core/modules/block/src/Tests/BlockHiddenRegionTest.php +++ b/core/modules/block/src/Tests/BlockHiddenRegionTest.php @@ -42,6 +42,7 @@ protected function setUp() { $this->drupalLogin($this->adminUser); $this->drupalPlaceBlock('search_form_block'); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/block/src/Tests/BlockTest.php b/core/modules/block/src/Tests/BlockTest.php index 5ab46e1..015d8a1 100644 --- a/core/modules/block/src/Tests/BlockTest.php +++ b/core/modules/block/src/Tests/BlockTest.php @@ -222,6 +222,7 @@ public function testBlockThemeSelector() { function testThemeName() { // Enable the help block. $this->drupalPlaceBlock('help_block', array('region' => 'help')); + $this->drupalPlaceBlock('system_tabs_block'); // Explicitly set the default and admin themes. $theme = 'block_test_specialchars_theme'; \Drupal::service('theme_handler')->install(array($theme)); diff --git a/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php b/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php index bc55ab2..27b0232 100644 --- a/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php +++ b/core/modules/block/src/Tests/NonDefaultBlockAdminTest.php @@ -24,6 +24,15 @@ class NonDefaultBlockAdminTest extends WebTestBase { public static $modules = array('block'); /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_tabs_block'); + } + + /** * Test non-default theme admin. */ function testNonDefaultBlockAdmin() { diff --git a/core/modules/block_content/src/Tests/BlockContentTestBase.php b/core/modules/block_content/src/Tests/BlockContentTestBase.php index 82139c0..4500fd0 100644 --- a/core/modules/block_content/src/Tests/BlockContentTestBase.php +++ b/core/modules/block_content/src/Tests/BlockContentTestBase.php @@ -60,6 +60,7 @@ protected function setUp() { } $this->adminUser = $this->drupalCreateUser($this->permissions); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/comment/src/Tests/CommentTestBase.php b/core/modules/comment/src/Tests/CommentTestBase.php index a52cbb3..3040c6a 100644 --- a/core/modules/comment/src/Tests/CommentTestBase.php +++ b/core/modules/comment/src/Tests/CommentTestBase.php @@ -27,7 +27,7 @@ * * @var array */ - public static $modules = array('comment', 'node', 'history', 'field_ui', 'datetime'); + public static $modules = ['block', 'comment', 'node', 'history', 'field_ui', 'datetime']; /** * An administrative user with permission to configure comment settings. @@ -86,6 +86,7 @@ protected function setUp() { // Create a test node authored by the web user. $this->node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1, 'uid' => $this->webUser->id())); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/config/src/Tests/ConfigEntityListTest.php b/core/modules/config/src/Tests/ConfigEntityListTest.php index ee58be5..209039a 100644 --- a/core/modules/config/src/Tests/ConfigEntityListTest.php +++ b/core/modules/config/src/Tests/ConfigEntityListTest.php @@ -23,7 +23,7 @@ class ConfigEntityListTest extends WebTestBase { * * @var array */ - public static $modules = array('config_test'); + public static $modules = ['block', 'config_test']; /** * {@inheritdoc} @@ -33,6 +33,7 @@ protected function setUp() { // Delete the override config_test entity since it is not required by this // test. \Drupal::entityManager()->getStorage('config_test')->load('override')->delete(); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationListUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationListUiTest.php index 4ceec20..634d934 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationListUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationListUiTest.php @@ -80,6 +80,7 @@ protected function setUp() { $this->config('locale.settings') ->set('translation.import_enabled', TRUE) ->save(); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php index 4c83a38..54decc8 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php @@ -24,6 +24,7 @@ class ConfigTranslationOverviewTest extends WebTestBase { * @var array */ public static $modules = [ + 'block', 'config_test', 'config_translation', 'config_translation_test', @@ -67,6 +68,7 @@ protected function setUp() { ConfigurableLanguage::createFromLangcode($langcode)->save(); } $this->localeStorage = $this->container->get('locale.storage'); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php index 4bbb408..0fb16c7 100644 --- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php +++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php @@ -28,7 +28,7 @@ class ConfigTranslationUiTest extends WebTestBase { * * @var array */ - public static $modules = array('node', 'contact', 'contact_test', 'config_translation', 'config_translation_test', 'views', 'views_ui', 'contextual', 'filter', 'filter_test'); + public static $modules = ['block', 'node', 'contact', 'contact_test', 'config_translation', 'config_translation_test', 'views', 'views_ui', 'contextual', 'filter', 'filter_test']; /** * Languages to enable. @@ -101,6 +101,7 @@ protected function setUp() { ConfigurableLanguage::createFromLangcode($langcode)->save(); } $this->localeStorage = $this->container->get('locale.storage'); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/contact/src/Tests/ContactSitewideTest.php b/core/modules/contact/src/Tests/ContactSitewideTest.php index 87d693a..9cb6910 100644 --- a/core/modules/contact/src/Tests/ContactSitewideTest.php +++ b/core/modules/contact/src/Tests/ContactSitewideTest.php @@ -39,6 +39,7 @@ class ContactSitewideTest extends WebTestBase { protected function setUp() { parent::setUp(); $this->drupalPlaceBlock('system_breadcrumb_block'); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/contact/src/Tests/ContactStorageTest.php b/core/modules/contact/src/Tests/ContactStorageTest.php index 5d62e10..f18d10e 100644 --- a/core/modules/contact/src/Tests/ContactStorageTest.php +++ b/core/modules/contact/src/Tests/ContactStorageTest.php @@ -28,13 +28,14 @@ class ContactStorageTest extends ContactSitewideTest { * * @var array */ - public static $modules = array( + public static $modules = [ + 'block', 'text', 'contact', 'field_ui', 'contact_storage_test', 'contact_test', - ); + ]; /** * Tests configuration options and the site-wide contact form. diff --git a/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php b/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php index 7b7fe12..62b2768 100644 --- a/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php +++ b/core/modules/field_ui/src/Tests/EntityDisplayModeTest.php @@ -19,9 +19,18 @@ class EntityDisplayModeTest extends WebTestBase { /** * Modules to enable. * - * @var array + * @var string[] */ - public static $modules = array('entity_test', 'field_ui'); + public static $modules = ['block', 'entity_test', 'field_ui']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_local_actions_block'); + } /** * Tests the EntityViewMode user interface. diff --git a/core/modules/field_ui/src/Tests/FieldUIRouteTest.php b/core/modules/field_ui/src/Tests/FieldUIRouteTest.php index 332a87d..4a6380b 100644 --- a/core/modules/field_ui/src/Tests/FieldUIRouteTest.php +++ b/core/modules/field_ui/src/Tests/FieldUIRouteTest.php @@ -23,7 +23,7 @@ class FieldUIRouteTest extends WebTestBase { * * @var string[] */ - public static $modules = array('entity_test', 'field_ui'); + public static $modules = ['block', 'entity_test', 'field_ui']; /** * {@inheritdoc} @@ -32,6 +32,7 @@ protected function setUp() { parent::setUp(); $this->drupalLogin($this->rootUser); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/core/modules/field_ui/src/Tests/ManageFieldsTest.php index 3b90bff..28517fc 100644 --- a/core/modules/field_ui/src/Tests/ManageFieldsTest.php +++ b/core/modules/field_ui/src/Tests/ManageFieldsTest.php @@ -66,7 +66,10 @@ class ManageFieldsTest extends WebTestBase { */ protected function setUp() { parent::setUp(); + $this->drupalPlaceBlock('system_breadcrumb_block'); + $this->drupalPlaceBlock('system_local_actions_block'); + $this->drupalPlaceBlock('system_tabs_block'); // Create a test user. $admin_user = $this->drupalCreateUser(array('access content', 'administer content types', 'administer node fields', 'administer node form display', 'administer node display', 'administer taxonomy', 'administer taxonomy_term fields', 'administer taxonomy_term display', 'administer users', 'administer account settings', 'administer user display', 'bypass node access')); diff --git a/core/modules/filter/src/Tests/FilterAdminTest.php b/core/modules/filter/src/Tests/FilterAdminTest.php index 7e6a2d3..897943cf 100644 --- a/core/modules/filter/src/Tests/FilterAdminTest.php +++ b/core/modules/filter/src/Tests/FilterAdminTest.php @@ -22,7 +22,7 @@ class FilterAdminTest extends WebTestBase { /** * {@inheritdoc} */ - public static $modules = array('filter', 'node'); + public static $modules = ['block', 'filter', 'node']; /** * An user with administration permissions. @@ -105,6 +105,7 @@ protected function setUp() { user_role_grant_permissions('authenticated', array($basic_html_format->getPermissionName())); user_role_grant_permissions('anonymous', array($restricted_html_format->getPermissionName())); $this->drupalLogin($this->adminUser); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/filter/src/Tests/FilterFormatAccessTest.php b/core/modules/filter/src/Tests/FilterFormatAccessTest.php index 029c60b..5df5bdc 100644 --- a/core/modules/filter/src/Tests/FilterFormatAccessTest.php +++ b/core/modules/filter/src/Tests/FilterFormatAccessTest.php @@ -24,7 +24,7 @@ class FilterFormatAccessTest extends WebTestBase { * * @var array */ - public static $modules = array('filter', 'node'); + public static $modules = ['block', 'filter', 'node']; /** * A user with administrative permissions. @@ -114,6 +114,7 @@ protected function setUp() { $this->secondAllowedFormat->getPermissionName(), $this->disallowedFormat->getPermissionName(), )); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/forum/src/Tests/ForumTest.php b/core/modules/forum/src/Tests/ForumTest.php index 73089e3..e80e9ad 100644 --- a/core/modules/forum/src/Tests/ForumTest.php +++ b/core/modules/forum/src/Tests/ForumTest.php @@ -115,6 +115,7 @@ protected function setUp() { 'access comments', )); $this->drupalPlaceBlock('help_block', array('region' => 'help')); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/language/src/Tests/LanguagePathMonolingualTest.php b/core/modules/language/src/Tests/LanguagePathMonolingualTest.php index c20a57e..a4c92c0 100644 --- a/core/modules/language/src/Tests/LanguagePathMonolingualTest.php +++ b/core/modules/language/src/Tests/LanguagePathMonolingualTest.php @@ -21,7 +21,7 @@ class LanguagePathMonolingualTest extends WebTestBase { * * @var array */ - public static $modules = array('language', 'path'); + public static $modules = ['block', 'language', 'path']; protected function setUp() { parent::setUp(); @@ -56,6 +56,7 @@ protected function setUp() { // Set language detection to URL. $edit = array('language_interface[enabled][language-url]' => TRUE); $this->drupalPostForm('admin/config/regional/language/detection', $edit, t('Save settings')); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/language/src/Tests/LanguageTourTest.php b/core/modules/language/src/Tests/LanguageTourTest.php index 98418b6..91cbdab 100644 --- a/core/modules/language/src/Tests/LanguageTourTest.php +++ b/core/modules/language/src/Tests/LanguageTourTest.php @@ -28,7 +28,7 @@ class LanguageTourTest extends TourTestBase { * * @var array */ - public static $modules = array('language', 'tour'); + public static $modules = ['block', 'language', 'tour']; /** * {@inheritdoc} @@ -37,6 +37,7 @@ protected function setUp() { parent::setUp(); $this->adminUser = $this->drupalCreateUser(array('administer languages', 'access tour')); $this->drupalLogin($this->adminUser); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/node/src/Tests/NodeTranslationUITest.php b/core/modules/node/src/Tests/NodeTranslationUITest.php index c392750..013466c 100644 --- a/core/modules/node/src/Tests/NodeTranslationUITest.php +++ b/core/modules/node/src/Tests/NodeTranslationUITest.php @@ -28,6 +28,7 @@ class NodeTranslationUITest extends ContentTranslationUITestBase { 'languages:language_interface', 'theme', 'user.permissions', + 'route.name', 'route.menu_active_trails:account', 'route.menu_active_trails:footer', 'route.menu_active_trails:main', diff --git a/core/modules/node/src/Tests/PageEditTest.php b/core/modules/node/src/Tests/PageEditTest.php index 9082dca..9a9f28c 100644 --- a/core/modules/node/src/Tests/PageEditTest.php +++ b/core/modules/node/src/Tests/PageEditTest.php @@ -16,11 +16,19 @@ class PageEditTest extends NodeTestBase { protected $webUser; protected $adminUser; + /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block', 'node', 'datetime']; + protected function setUp() { parent::setUp(); $this->webUser = $this->drupalCreateUser(array('edit own page content', 'create page content')); $this->adminUser = $this->drupalCreateUser(array('bypass node access', 'administer nodes')); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php index c471cea..2965267 100644 --- a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php +++ b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php @@ -103,6 +103,8 @@ function testPageCacheTags() { 'config:block.block.bartik_main_menu', 'config:block.block.bartik_account_menu', 'config:block.block.bartik_messages', + 'config:block.block.bartik_local_actions', + 'config:block.block.bartik_tabs', 'node_view', 'node:' . $node_1->id(), 'user:' . $author_1->id(), @@ -137,6 +139,8 @@ function testPageCacheTags() { 'config:block.block.bartik_main_menu', 'config:block.block.bartik_account_menu', 'config:block.block.bartik_messages', + 'config:block.block.bartik_local_actions', + 'config:block.block.bartik_tabs', 'node_view', 'node:' . $node_2->id(), 'user:' . $author_2->id(), diff --git a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php index a99ea45..c897616 100644 --- a/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php +++ b/core/modules/search/src/Tests/SearchConfigSettingsFormTest.php @@ -58,6 +58,7 @@ protected function setUp() { // Enable the search block. $this->drupalPlaceBlock('search_form_block'); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/search/src/Tests/SearchPageTextTest.php b/core/modules/search/src/Tests/SearchPageTextTest.php index ad311d6..368a1f0 100644 --- a/core/modules/search/src/Tests/SearchPageTextTest.php +++ b/core/modules/search/src/Tests/SearchPageTextTest.php @@ -23,11 +23,22 @@ class SearchPageTextTest extends SearchTestBase { */ protected $searchingUser; + /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block']; + + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp(); // Create user. $this->searchingUser = $this->drupalCreateUser(array('search content', 'access user profiles', 'use advanced search')); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/shortcut/src/Tests/ShortcutSetsTest.php b/core/modules/shortcut/src/Tests/ShortcutSetsTest.php index 7511205..948d0db 100644 --- a/core/modules/shortcut/src/Tests/ShortcutSetsTest.php +++ b/core/modules/shortcut/src/Tests/ShortcutSetsTest.php @@ -18,6 +18,22 @@ class ShortcutSetsTest extends ShortcutTestBase { /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_local_actions_block'); + } + + /** * Tests creating a shortcut set. */ function testShortcutSetAdd() { diff --git a/core/modules/simpletest/src/Tests/BrowserTest.php b/core/modules/simpletest/src/Tests/BrowserTest.php index 02422e7..6bfaf14 100644 --- a/core/modules/simpletest/src/Tests/BrowserTest.php +++ b/core/modules/simpletest/src/Tests/BrowserTest.php @@ -24,6 +24,22 @@ class BrowserTest extends WebTestBase { protected static $cookieSet = FALSE; /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_tabs_block'); + } + + /** * Test \Drupal\simpletest\WebTestBase::getAbsoluteUrl(). */ function testGetAbsoluteUrl() { diff --git a/core/modules/system/config/schema/system.schema.yml b/core/modules/system/config/schema/system.schema.yml index 7cde50d..3b7ed3f 100644 --- a/core/modules/system/config/schema/system.schema.yml +++ b/core/modules/system/config/schema/system.schema.yml @@ -353,6 +353,17 @@ block.settings.system_menu_block:*: type: integer label: 'Maximum number of levels' +block.settings.system_tabs_block: + type: block_settings + label: 'Tabs block' + mapping: + primary: + type: boolean + label: 'Whether primary tabs are shown' + secondary: + type: boolean + label: 'Whether secondary tabs are shown' + condition.plugin.request_path: type: condition.plugin mapping: diff --git a/core/modules/system/src/Plugin/Block/SystemLocalActionsBlock.php b/core/modules/system/src/Plugin/Block/SystemLocalActionsBlock.php new file mode 100644 index 0000000..23a65c0 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemLocalActionsBlock.php @@ -0,0 +1,129 @@ +localActionManager = $local_action_manager; + $this->routeMatch = $route_match; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('plugin.manager.menu.local_action'), + $container->get('current_route_match') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return ['label_display' => FALSE]; + } + + /** + * {@inheritdoc} + */ + public function build() { + $build = []; + $links = menu_local_tasks(); + $route_name = $this->routeMatch->getRouteName(); + $local_actions = $this->localActionManager->getActionsForRoute($route_name) + $links['actions']; + if (empty($local_actions)) { + return []; + } + + $build['local_actions'] = $local_actions; + + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // The "Primary admin actions" block is never cacheable because hooks creating local + // actions don't provide cacheability metadata. + // @todo Remove after https://www.drupal.org/node/2511516 has landed. + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = $this->t('This block is never cacheable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + // @todo Remove after https://www.drupal.org/node/2511516 has landed. + return 0; + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + return ['route.name']; + } + +} diff --git a/core/modules/system/src/Plugin/Block/SystemTabsBlock.php b/core/modules/system/src/Plugin/Block/SystemTabsBlock.php new file mode 100644 index 0000000..9168455 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemTabsBlock.php @@ -0,0 +1,146 @@ + FALSE, + 'primary' => TRUE, + 'secondary' => TRUE, + ]; + } + + /** + * {@inheritdoc} + */ + public function build() { + $config = $this->configuration; + + $tabs = [ + '#theme' => 'menu_local_tasks', + ]; + + // Add only selected levels for the printed output. + if ($config['primary']) { + $tabs += [ + '#primary' => menu_primary_local_tasks(), + ]; + } + if ($config['secondary']) { + $tabs += [ + '#secondary' => menu_secondary_local_tasks(), + ]; + } + + if (empty($tabs['#primary']) && empty($tabs['#secondary'])) { + return []; + } + + $build['tabs'] = $tabs; + + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // The "Page actions" block is never cacheable because of hooks creating + // local tasks doesn't provide cacheability metadata. + // @todo Remove after https://www.drupal.org/node/2511516 has landed. + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = $this->t('This block is never cacheable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + // @todo Remove after https://www.drupal.org/node/2511516 has landed. + return 0; + } + + /** + * {@inheritdoc} + */ + public function getCacheContexts() { + return ['route.name']; + } + + /** + * {@inheritdoc} + */ + public function blockForm($form, FormStateInterface $form_state) { + $config = $this->configuration; + $defaults = $this->defaultConfiguration(); + + $form['levels'] = array( + '#type' => 'details', + '#title' => $this->t('Shown tabs'), + '#description' => $this->t('Select tabs being shown in the block'), + // Open if not set to defaults. + '#open' => $defaults['primary'] !== $config['primary'] || $defaults['secondary'] !== $config['secondary'], + ); + $form['levels']['primary'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Show primary tabs'), + '#default_value' => $config['primary'], + ]; + $form['levels']['secondary'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Show secondary tabs'), + '#default_value' => $config['secondary'], + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function blockSubmit($form, FormStateInterface $form_state) { + $levels = $form_state->getValue('levels'); + $this->configuration['primary'] = $levels['primary']; + $this->configuration['secondary'] = $levels['secondary']; + } + +} diff --git a/core/modules/system/src/Tests/Menu/LocalActionTest.php b/core/modules/system/src/Tests/Menu/LocalActionTest.php index c049198..bd1c593 100644 --- a/core/modules/system/src/Tests/Menu/LocalActionTest.php +++ b/core/modules/system/src/Tests/Menu/LocalActionTest.php @@ -18,9 +18,20 @@ class LocalActionTest extends WebTestBase { /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block', 'menu_test']; + + /** * {@inheritdoc} */ - public static $modules = array('menu_test'); + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_local_actions_block'); + } /** * Tests appearance of local actions. diff --git a/core/modules/system/src/Tests/Menu/LocalTasksTest.php b/core/modules/system/src/Tests/Menu/LocalTasksTest.php index b7824ef..168b037 100644 --- a/core/modules/system/src/Tests/Menu/LocalTasksTest.php +++ b/core/modules/system/src/Tests/Menu/LocalTasksTest.php @@ -17,7 +17,28 @@ */ class LocalTasksTest extends WebTestBase { - public static $modules = array('menu_test', 'entity_test'); + /** + * Modules to enable. + * + * @var string[] + */ + public static $modules = ['block', 'menu_test', 'entity_test']; + + /** + * The local tasks block under testing. + * + * @var \Drupal\block\Entity\Block + */ + protected $sut; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->sut = $this->drupalPlaceBlock('system_tabs_block', ['id' => 'tabs_block']); + } /** * Asserts local tasks in the page output. @@ -48,6 +69,20 @@ protected function assertLocalTasks(array $routes, $level = 0) { } /** + * Asserts that the local tasks on the specified level are not being printed. + * + * @param int $level + * (optional) The local tasks level to assert; 0 for primary, 1 for + * secondary. Defaults to 0. + */ + protected function assertNoLocalTasks($level = 0) { + $elements = $this->xpath('//*[contains(@class, :class)]//a', array( + ':class' => $level == 0 ? 'tabs primary' : 'tabs secondary', + )); + $this->assertFalse(count($elements), 'Local tasks not found.'); + } + + /** * Tests the plugin based local tasks. */ public function testPluginLocalTask() { @@ -135,4 +170,52 @@ public function testPluginLocalTask() { $this->assertEqual('upcasting sub2', (string) $result[0]->a, 'The "upcasting sub2" tab is active.'); } + /** + * Tests that local task blocks are configurable to show a specific level. + */ + public function testLocalTaskBlock() { + // Remove the default block and create a new one. + $this->sut->delete(); + + $this->sut = $this->drupalPlaceBlock('system_tabs_block', [ + 'id' => 'tabs_block', + 'primary' => TRUE, + 'secondary' => FALSE, + ]); + + $this->drupalGet(Url::fromRoute('menu_test.local_task_test_tasks_settings')); + + // Verify that local tasks in the first level appear. + $this->assertLocalTasks([ + ['menu_test.local_task_test_tasks_view', []], + ['menu_test.local_task_test_tasks_edit', []], + ['menu_test.local_task_test_tasks_settings', []], + ]); + + // Verify that local tasks in the second level doesn't appear. + $this->assertNoLocalTasks(1); + + $this->sut->delete(); + $this->sut = $this->drupalPlaceBlock('system_tabs_block', [ + 'id' => 'tabs_block', + 'primary' => FALSE, + 'secondary' => TRUE, + ]); + + $this->drupalGet(Url::fromRoute('menu_test.local_task_test_tasks_settings')); + + // Verify that local tasks in the first level doesn't appear. + $this->assertNoLocalTasks(0); + + // Verify that local tasks in the second level appear. + $sub_tasks = [ + ['menu_test.local_task_test_tasks_settings_sub1', []], + ['menu_test.local_task_test_tasks_settings_sub2', []], + ['menu_test.local_task_test_tasks_settings_sub3', []], + ['menu_test.local_task_test_tasks_settings_derived', ['placeholder' => 'derive1']], + ['menu_test.local_task_test_tasks_settings_derived', ['placeholder' => 'derive2']], + ]; + $this->assertLocalTasks($sub_tasks, 1); + } + } diff --git a/core/modules/system/src/Tests/Menu/MenuRouterTest.php b/core/modules/system/src/Tests/Menu/MenuRouterTest.php index ef78c7b..0f2fb5e 100644 --- a/core/modules/system/src/Tests/Menu/MenuRouterTest.php +++ b/core/modules/system/src/Tests/Menu/MenuRouterTest.php @@ -43,6 +43,7 @@ protected function setUp() { parent::setUp(); $this->drupalPlaceBlock('system_menu_block:tools'); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/system/src/Tests/Menu/MenuTranslateTest.php b/core/modules/system/src/Tests/Menu/MenuTranslateTest.php index e316c95..e02a304 100644 --- a/core/modules/system/src/Tests/Menu/MenuTranslateTest.php +++ b/core/modules/system/src/Tests/Menu/MenuTranslateTest.php @@ -23,7 +23,16 @@ class MenuTranslateTest extends WebTestBase { * * @var array */ - public static $modules = array('menu_test'); + public static $modules = ['block', 'menu_test']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->drupalPlaceBlock('system_tabs_block'); + } /** * Tests _menu_translate(). diff --git a/core/modules/system/src/Tests/System/DateTimeTest.php b/core/modules/system/src/Tests/System/DateTimeTest.php index 9f0b0ac..9817fc6 100644 --- a/core/modules/system/src/Tests/System/DateTimeTest.php +++ b/core/modules/system/src/Tests/System/DateTimeTest.php @@ -22,13 +22,14 @@ class DateTimeTest extends WebTestBase { * * @var array */ - public static $modules = array('node', 'language'); + public static $modules = ['block', 'node', 'language']; protected function setUp() { parent::setUp(); // Create admin user and log in admin user. $this->drupalLogin ($this->drupalCreateUser(array('administer site configuration'))); + $this->drupalPlaceBlock('system_local_actions_block'); } /** diff --git a/core/modules/system/src/Tests/System/ThemeTest.php b/core/modules/system/src/Tests/System/ThemeTest.php index 84745b7..e97c75b 100644 --- a/core/modules/system/src/Tests/System/ThemeTest.php +++ b/core/modules/system/src/Tests/System/ThemeTest.php @@ -30,7 +30,7 @@ class ThemeTest extends WebTestBase { * * @var array */ - public static $modules = array('node', 'block', 'file'); + public static $modules = ['node', 'block', 'file']; protected function setUp() { parent::setUp(); @@ -40,6 +40,7 @@ protected function setUp() { $this->adminUser = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer themes', 'bypass node access', 'administer blocks')); $this->drupalLogin($this->adminUser); $this->node = $this->drupalCreateNode(); + $this->drupalPlaceBlock('system_tabs_block'); } /** diff --git a/core/modules/system/system.module b/core/modules/system/system.module index a826e69..028190a 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -805,6 +805,14 @@ function system_preprocess_block(&$variables) { } break; + case 'system_local_actions_block': + $variables['content'] = $variables['content']['local_actions']; + break; + + case 'system_tabs_block': + $variables['content'] = $variables['content']['tabs']; + break; + case 'system_powered_by_block': $variables['attributes']['role'] = 'complementary'; break; diff --git a/core/modules/system/templates/page.html.twig b/core/modules/system/templates/page.html.twig index c5a3711..b80310e 100644 --- a/core/modules/system/templates/page.html.twig +++ b/core/modules/system/templates/page.html.twig @@ -32,10 +32,6 @@ * - title_suffix: Additional output populated by modules, intended to be * displayed after the main title tag that appears in the template. * - messages: Status and error messages. Should be displayed prominently. - * - tabs: Tabs linking to any sub-pages beneath the current page (e.g., the - * view and edit tabs when displaying a node). - * - action_links: Actions local to the page, such as "Add menu" on the menu - * administration interface. * - node: Fully loaded node, if there is an automatically-loaded node * associated with the page and the node ID is the second argument in the * page's path (e.g. node/12345 and node/12345/revisions, but not @@ -110,13 +106,6 @@