diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 03d0df0..5a9e1eb 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -2512,6 +2512,12 @@ function drupal_common_theme() { 'variables' => array('display' => NULL), 'template' => 'status-messages', ), + // @TODO change this to status_messages once the messages are gone from + // template_preprocess_page + 'status_messages_block' => array( + 'variables' => array('status_headings' => array(), 'message_list' => NULL), + 'template' => 'status-messages', + ), 'links' => array( 'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array(), 'set_active_class' => FALSE), 'template' => 'links', 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..813da5a --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageActionsBlock.php @@ -0,0 +1,136 @@ +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 array( + 'label_display' => FALSE, + ); + } + + /** + * {@inheritdoc} + */ + public function build() { + $build = array(); + $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']; + + $build['action_links'] = array( + '#markup' => $action_links, + ); + + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, array &$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 isCacheable() { + // The "Page Actions" block is never cacheable, because its contents depends + // on access checks, which are currently uncacheable. + // @todo Make cacheable once https://drupal.org/node/2287071 lands. + return FALSE; + } + +} diff --git a/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php b/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php new file mode 100644 index 0000000..ad9e237 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageMessagesBlock.php @@ -0,0 +1,134 @@ +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 array( + 'label_display' => FALSE, + ); + } + + /** + * {@inheritdoc} + */ + public function build() { + + $build['messages'] = array( + // @TODO change this to status_messages once the messages are gone from + // template_preprocess_page + '#theme' => 'status_messages_block', + '#pre_render' => array(array($this, 'getMessages')), + ); + $build['messages']['#status_headings'] = array( + 'status' => t('Status message'), + 'error' => t('Error message'), + 'warning' => t('Warning message'), + ); + + return $build; + } + + /** + * Gets messages in the pre-render stage. + * + * @param $element + * @return mixed + */ + public function getMessages($element) { + if (!isset(static::$messages)) { + static::$messages = drupal_get_messages(); + } + $element['#message_list'] = static::$messages; + return $element; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, array &$form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // @see ::isCacheable() + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = $this->t('This block is never cacheable, it is not configurable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function isCacheable() { + // The page messages block is never cacheable, because its contents are + // session-specific and caching is useless. + return FALSE; + } + +} 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..bd9ac2c --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageTabsBlock.php @@ -0,0 +1,102 @@ +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 array( + 'label_display' => FALSE, + ); + } + + /** + * {@inheritdoc} + */ + public function build() { + $build['tabs']['#markup'] = menu_local_tabs(); + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, array &$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 isCacheable() { + // The "Page Tabs" block is never cacheable, because its contents depends + // on access checks, which are currently uncacheable. + // @todo Make cacheable once https://drupal.org/node/2287071 lands. + return FALSE; + } + +} diff --git a/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php b/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php new file mode 100644 index 0000000..b3b6c86 --- /dev/null +++ b/core/modules/system/src/Plugin/Block/SystemPageTitleBlock.php @@ -0,0 +1,135 @@ +configFactory = $config_factory; + $this->titleResolver = $title_resolver; + $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('title_resolver'), + $container->get('request_stack') + ); + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return array( + 'label_display' => FALSE, + ); + } + + /** + * {@inheritdoc} + */ + public function build() { + $build = array(); + $title = ''; + $request = $this->requestStack->getCurrentRequest(); + if ($route = $request->attributes->get(routeObjectInterface::ROUTE_OBJECT)) { + $title = $this->titleResolver->getTitle($request, $route); + } + + $build['title'] = array( + '#markup' => $title, + ); + + return $build; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, array &$form_state) { + $form = parent::buildConfigurationForm($form, $form_state); + + // The 'Page title' block is never cacheable, because it may be dynamic. + $form['cache']['#disabled'] = TRUE; + $form['cache']['#description'] = t('This block is never cacheable, it is not configurable.'); + $form['cache']['max_age']['#value'] = 0; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function isCacheable() { + // The 'Page title' block is never cacheable, because it may be dynamic. + return FALSE; + } + +} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index ac44ab5..f703fd1 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -160,13 +160,28 @@ function system_help($route_name, Request $request) { function system_theme() { return array_merge(drupal_common_theme(), array( // Normally theme suggestion templates are only picked up when they are in - // themes. We explicitly define the block__system_branding_block theme - // suggestion here so that the template in core/modules/system/templates - // is picked up. + // themes. We explicitly define theme suggestions here so that the + // block templates in core/modules/system/templates are picked up. 'block__system_branding_block' => array( 'base hook' => 'block', 'template' => 'block--system-branding-block', ), + 'block__system_page_title_block' => array( + 'base hook' => 'block', + 'template' => 'block--system-page-title-block', + ), + 'block__system_page_actions_block' => array( + 'base hook' => 'block', + 'template' => 'block--system-page-actions-block', + ), + 'block__system_page_tabs_block' => array( + 'base hook' => 'block', + 'template' => 'block--system-page-tabs-block', + ), + 'block__system_page_messages_block' => array( + 'base hook' => 'block', + 'template' => 'block--system-page-messages-block', + ), 'system_themes_page' => array( 'variables' => array( 'theme_groups' => array(), @@ -1072,6 +1087,27 @@ function system_preprocess_block(&$variables) { } break; + case 'system_page_title_block': + $variables['title'] = ''; + if($variables['content']['title']['#markup']) { + $variables['title'] = $variables['content']['title']['#markup']; + } + break; + + case 'system_page_actions_block': + $variables['action_links'] = ''; + if($variables['content']['action_links']['#markup']) { + $variables['action_links'] = $variables['content']['action_links']['#markup']; + } + break; + + case 'system_page_tabs_block': + $variables['tabs'] = ''; + if($variables['content']['tabs']['#markup']) { + $variables['tabs'] = $variables['content']['tabs']['#markup']; + } + 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-messages-block.html.twig b/core/modules/system/templates/block--system-page-messages-block.html.twig new file mode 100644 index 0000000..55175d7 --- /dev/null +++ b/core/modules/system/templates/block--system-page-messages-block.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Default theme implementation for page messages. + * + * Removes wrapper elements from block so that empty block does not appear when + * there are no messages. + * + * Available variables: + * - content: The content of this block. + * + * @ingroup themeable + */ +#} +{{ content }} 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/block--system-page-title-block.html.twig b/core/modules/system/templates/block--system-page-title-block.html.twig new file mode 100644 index 0000000..aca427c --- /dev/null +++ b/core/modules/system/templates/block--system-page-title-block.html.twig @@ -0,0 +1,23 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Default theme implementation for a page title. + * + * Available variables: + * - title_prefix: Additional output populated by modules, intended to be + * displayed in front of the main title tag that appears in the template. + * - title: The page title, for use in the actual content. + * - title_suffix: Additional output populated by modules, intended to be + * displayed after the main title tag that appears in the template. + * + * @ingroup themeable + */ +#} +{% block content %} + {{ title_prefix }} + {% if title %} +

{{ title }}

+ {% endif %} + {{ title_suffix }} +{% endblock %} 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 %} + + {% endif %} +{% endblock %} diff --git a/core/themes/bartik/templates/block--system-page-tabs-block.html.twig b/core/themes/bartik/templates/block--system-page-tabs-block.html.twig new file mode 100644 index 0000000..429ad98 --- /dev/null +++ b/core/themes/bartik/templates/block--system-page-tabs-block.html.twig @@ -0,0 +1,20 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Bartik's 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 %} + {% if tabs %} + + {% endif %} +{% endblock %} diff --git a/core/themes/bartik/templates/block--system-page-title-block.html.twig b/core/themes/bartik/templates/block--system-page-title-block.html.twig new file mode 100644 index 0000000..4bd27f1 --- /dev/null +++ b/core/themes/bartik/templates/block--system-page-title-block.html.twig @@ -0,0 +1,25 @@ +{% extends "@block/block.html.twig" %} +{# +/** + * @file + * Bartik's theme implementation for a page title. + * + * Available variables: + * - title_prefix: Additional output populated by modules, intended to be + * displayed in front of the main title tag that appears in the template. + * - title: The page title, for use in the actual content. + * - title_suffix: Additional output populated by modules, intended to be + * displayed after the main title tag that appears in the template. + * + * @ingroup themeable + */ +#} +{% block content %} + {{ title_prefix }} + {% if title %} +

+ {{ title }} +

+ {% endif %} + {{ title_suffix }} +{% endblock %} diff --git a/core/themes/bartik/templates/page.html.twig b/core/themes/bartik/templates/page.html.twig index 8c739bb..b8883cc 100644 --- a/core/themes/bartik/templates/page.html.twig +++ b/core/themes/bartik/templates/page.html.twig @@ -131,9 +131,7 @@ {% if messages %} -
- {{ messages }} -
+ {{ messages }} {% endif %} {% if page.featured %} diff --git a/core/themes/bartik/templates/status-messages.html.twig b/core/themes/bartik/templates/status-messages.html.twig new file mode 100644 index 0000000..87b8dcd --- /dev/null +++ b/core/themes/bartik/templates/status-messages.html.twig @@ -0,0 +1,58 @@ +{# +/** + * @file + * Default theme implementation for status messages. + * + * Displays status, error, and warning messages, grouped by type. + * + * An invisible heading identifies the messages for assistive technology. + * Sighted users see a colored box. See http://www.w3.org/TR/WCAG-TECHS/H69.html + * for info. + * + * Add an ARIA label to the contentinfo area so that assistive technology + * user agents will better describe this landmark. + * + * Available variables: + * - message_list: List of messages to be displayed, grouped by type. + * - status_headings: List of all status types. + * - display: (optional) May have a value of 'status' or 'error' when only + * displaying messages of that specific type. + * + * @see template_preprocess_status_messages() + * + * @ingroup themeable + */ +#} +{% set has_messages = 0 %} +{% for type, messages in message_list %} + {% if messages|length > 0 %} + {% set has_messages = 1 %} + {% endif %} +{% endfor %} + +{% if has_messages %} +
+{% for type, messages in message_list %} + +{% endfor %} +
+{% endif %}