diff --git a/core/includes/menu.inc b/core/includes/menu.inc index d578499..1c6d6fa 100644 --- a/core/includes/menu.inc +++ b/core/includes/menu.inc @@ -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 5d645e2..dd2d05d 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1384,14 +1384,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/Extension/ThemeHandler.php b/core/lib/Drupal/Core/Extension/ThemeHandler.php index f53bb0c..d234a7e 100644 --- a/core/lib/Drupal/Core/Extension/ThemeHandler.php +++ b/core/lib/Drupal/Core/Extension/ThemeHandler.php @@ -269,6 +269,8 @@ public function rebuildThemeData() { 'page_top' => 'Page top', 'page_bottom' => 'Page bottom', 'breadcrumb' => 'Breadcrumb', + 'tabs' => 'Page tabs', + 'actions' => 'Page actions', ), 'description' => '', 'features' => $this->defaultFeatures, diff --git a/core/lib/Drupal/Core/Menu/LocalActionManager.php b/core/lib/Drupal/Core/Menu/LocalActionManager.php index 208075c..be5d5db 100644 --- a/core/lib/Drupal/Core/Menu/LocalActionManager.php +++ b/core/lib/Drupal/Core/Menu/LocalActionManager.php @@ -174,6 +174,7 @@ public function getActionsForRoute($route_appears) { foreach ($this->instances[$route_appears] as $plugin_id => $plugin) { $route_name = $plugin->getRouteName(); $route_parameters = $plugin->getRouteParameters($this->routeMatch); + $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE); $links[$plugin_id] = array( '#theme' => 'menu_local_action', '#link' => array( @@ -181,10 +182,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' => $access->isAllowed(), '#weight' => $plugin->getWeight(), ); } + return $links; } diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php index 86136d0..54e95c4 100644 --- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php +++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php @@ -293,8 +293,8 @@ public function getTasksBuild($current_route_name) { $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) { + $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE); + if ($access->isAllowed()) { $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters); // The plugin may have been set active in getLocalTasksForRoute() if @@ -317,6 +317,7 @@ public function getTasksBuild($current_route_name) { } } } + return $build; } diff --git a/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php b/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php new file mode 100644 index 0000000..1124722 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php @@ -0,0 +1,134 @@ +configFactory = $config_factory; + $this->localActionManager = $local_action_manager; + $this->requestStack = $request_stack; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('config.factory'), + $container->get('plugin.manager.menu.local_action'), + $container->get('request_stack') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return ['label_display' => FALSE]; + } + + /** + * {@inheritdoc} + */ + public function build() { + $build = []; + $links = menu_local_tasks(); + $request = $this->requestStack->getCurrentRequest(); + $route_name = $request->attributes->get(RouteObjectInterface::ROUTE_NAME); + $action_links = $this->localActionManager->getActionsForRoute($route_name) + $links['actions']; + if (empty($action_links)) { + return []; + } + + $build['action_links'] = $action_links; + + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // The "Page actions" block is never cacheable, due to access checking. + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = $this->t('This block is never cacheable because access checking is needed, it is not configurable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + // @todo Make me cacheable now that https://drupal.org/node/2287071 has landed. + return 0; + } + +} diff --git a/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php b/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php new file mode 100644 index 0000000..7087749 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php @@ -0,0 +1,103 @@ +configFactory = $config_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('config.factory') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return ['label_display' => FALSE]; + } + + /** + * {@inheritdoc} + */ + public function build() { + $tabs = menu_local_tabs(); + if (empty($tabs)) { + return []; + } + $build['tabs'] = $tabs; + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // The "Page tabs" block is never cacheable, due to access checking. + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = $this->t('This block is never cacheable because access checking is needed, it is not configurable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getCacheMaxAge() { + // @todo Make cacheable now that https://drupal.org/node/2287071 has landed. + return 0; + } + +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 96f0083..99785f9 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -169,6 +169,14 @@ function system_theme() { 'block__system_messages_block' => array( 'base hook' => 'block', ), + 'block__system_page_actions_block' => [ + 'base hook' => 'block', + 'template' => 'block--system-page-actions-block', + ], + 'block__system_page_tabs_block' => [ + 'base hook' => 'block', + 'template' => 'block--system-page-tabs-block', + ], 'block__system_menu_block' => array( 'render element' => 'elements', 'base hook' => 'block', @@ -782,6 +790,14 @@ function system_preprocess_block(&$variables) { } break; + case 'system_page_actions_block': + $variables['action_links'] = $variables['content']['action_links']; + break; + + case 'system_page_tabs_block': + $variables['tabs'] = $variables['content']['tabs']; + break; + case 'system_powered_by_block': $variables['attributes']['role'] = 'complementary'; break; diff --git a/core/modules/system/templates/block--system-page-actions-block.html.twig b/core/modules/system/templates/block--system-page-actions-block.html.twig new file mode 100644 index 0000000..a5972dc --- /dev/null +++ b/core/modules/system/templates/block--system-page-actions-block.html.twig @@ -0,0 +1,18 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Default theme implementation for page local actions. + * + * Available variables: + * - action_links: Actions local to the page, such as "Add menu" on the menu + * administration interface. + * + * @ingroup themeable + */ +#} +{% block content %} + {% if action_links %} + + {% endif %} +{% endblock %} diff --git a/core/modules/system/templates/block--system-page-tabs-block.html.twig b/core/modules/system/templates/block--system-page-tabs-block.html.twig new file mode 100644 index 0000000..780abe7 --- /dev/null +++ b/core/modules/system/templates/block--system-page-tabs-block.html.twig @@ -0,0 +1,16 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Default theme implementation for page tabs. + * + * Available variables: + * - tabs: The Tabs linking to any sub-pages beneath the current page (e.g., the + * view and edit tabs when displaying a node). + * + * @ingroup themeable + */ +#} +{% block content %} + {{ tabs }} +{% endblock %} diff --git a/core/modules/system/templates/page.html.twig b/core/modules/system/templates/page.html.twig index c5a3711..6200539 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 @@ -52,6 +48,8 @@ * - page.sidebar_second: Items for the second sidebar. * - page.footer: Items for the footer region. * - page.breadcrumb: Items for the breadcrumb region. + * - page.tabs: Items for the tabs region. + * - page.actions: Items for the actions region. * * @see template_preprocess_page() * @see html.html.twig @@ -111,11 +109,9 @@ {% endif %} {{ title_suffix }} - {{ tabs }} + {{ page.tabs }} - {% if action_links %} - - {% endif %} + {{ page.actions }} {{ page.content }} {# /.layout-content #} diff --git a/core/profiles/standard/config/install/block.block.bartik_page_actions.yml b/core/profiles/standard/config/install/block.block.bartik_page_actions.yml new file mode 100644 index 0000000..4e051e8 --- /dev/null +++ b/core/profiles/standard/config/install/block.block.bartik_page_actions.yml @@ -0,0 +1,18 @@ +id: bartik_page_actions +theme: bartik +weight: 10 +status: true +langcode: en +region: actions +plugin: system_page_actions_block +settings: + id: system_page_actions_block + label: Page actions + provider: system + label_display: '0' +dependencies: + module: + - system + theme: + - bartik +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.bartik_page_tabs.yml b/core/profiles/standard/config/install/block.block.bartik_page_tabs.yml new file mode 100644 index 0000000..c8cf59a --- /dev/null +++ b/core/profiles/standard/config/install/block.block.bartik_page_tabs.yml @@ -0,0 +1,18 @@ +id: bartik_page_tabs +theme: bartik +weight: 10 +status: true +langcode: en +region: tabs +plugin: system_page_tabs_block +settings: + id: system_page_tabs_block + label: Page tabs + provider: system + label_display: '0' +dependencies: + module: + - system + theme: + - bartik +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.seven_page_actions.yml b/core/profiles/standard/config/install/block.block.seven_page_actions.yml new file mode 100644 index 0000000..7802a57 --- /dev/null +++ b/core/profiles/standard/config/install/block.block.seven_page_actions.yml @@ -0,0 +1,18 @@ +id: page_actions +theme: seven +weight: 0 +status: true +langcode: en +region: actions +plugin: system_page_actions_block +settings: + id: system_page_actions_block + label: Page actions + provider: system + label_display: '0' +dependencies: + module: + - system + theme: + - seven +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.seven_page_tabs.yml b/core/profiles/standard/config/install/block.block.seven_page_tabs.yml new file mode 100644 index 0000000..9b9995a --- /dev/null +++ b/core/profiles/standard/config/install/block.block.seven_page_tabs.yml @@ -0,0 +1,18 @@ +id: page_tabs +theme: seven +weight: 0 +status: true +langcode: en +region: tabs +plugin: system_page_tabs_block +settings: + id: system_page_tabs_block + label: Page tabs + provider: system + label_display: '0' +dependencies: + module: + - system + theme: + - seven +visibility: { } diff --git a/core/themes/bartik/bartik.info.yml b/core/themes/bartik/bartik.info.yml index fb8f2fb..444992e 100644 --- a/core/themes/bartik/bartik.info.yml +++ b/core/themes/bartik/bartik.info.yml @@ -24,6 +24,8 @@ regions: highlighted: Highlighted featured_top: 'Featured top' breadcrumb: Breadcrumb + tabs: Tabs + actions: Actions content: Content sidebar_first: 'Sidebar first' sidebar_second: 'Sidebar second' diff --git a/core/themes/bartik/templates/block--system-page-actions-block.html.twig b/core/themes/bartik/templates/block--system-page-actions-block.html.twig new file mode 100644 index 0000000..b8283b5 --- /dev/null +++ b/core/themes/bartik/templates/block--system-page-actions-block.html.twig @@ -0,0 +1,20 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Bartik's theme implementation for page local actions. + * + * Available variables: + * - action_links: Actions local to the page, such as "Add menu" on the menu + * administration interface. + * + * @ingroup themeable + */ +#} +{% block content %} + {% if action_links %} +