diff --git a/core/includes/theme.inc b/core/includes/theme.inc index b1a911a..092eadf 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -1290,9 +1290,6 @@ function template_preprocess_html(&$variables) { function template_preprocess_page(&$variables) { $language_interface = \Drupal::languageManager()->getCurrentLanguage(); - // Move some variables to the top level for themer convenience and template cleanliness. - $variables['title'] = $variables['page']['#title']; - foreach (\Drupal::theme()->getActiveTheme()->getRegions() as $region) { if (!isset($variables['page'][$region])) { $variables['page'][$region] = array(); @@ -1413,6 +1410,10 @@ function template_preprocess_maintenance_page(&$variables) { $variables['logo'] = theme_get_setting('logo.url'); $variables['site_name'] = $site_config->get('name'); $variables['site_slogan'] = $site_config->get('slogan'); + + // Maintenance page and install page need page title in variable because there + // are no blocks. + $variables['title'] = $variables['page']['#title']; } /** @@ -1659,6 +1660,9 @@ function drupal_common_theme() { 'page' => array( 'render element' => 'page', ), + 'page_title' => array( + 'variables' => array('title' => NULL), + ), 'region' => array( 'render element' => 'elements', ), diff --git a/core/lib/Drupal/Core/Block/MainContentBlockPluginInterface.php b/core/lib/Drupal/Core/Block/MainContentBlockPluginInterface.php index 2516348..38da7b3 100644 --- a/core/lib/Drupal/Core/Block/MainContentBlockPluginInterface.php +++ b/core/lib/Drupal/Core/Block/MainContentBlockPluginInterface.php @@ -10,7 +10,7 @@ /** * The interface for "main page content" blocks. * - * A main page content block represents the content returns by the controller. + * A main page content block represents the content returned by the controller. * * @ingroup block_api */ diff --git a/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php b/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php new file mode 100644 index 0000000..7ff4c2c --- /dev/null +++ b/core/lib/Drupal/Core/Block/Plugin/Block/PageTitleBlock.php @@ -0,0 +1,55 @@ +title = $title; + return $this; + } + + /** + * {@inheritdoc} + */ + public function defaultConfiguration() { + return ['label_display' => FALSE]; + } + + /** + * {@inheritdoc} + */ + public function build() { + return [ + '#type' => 'page_title', + '#title' => $this->title, + ]; + } + +} diff --git a/core/lib/Drupal/Core/Block/TitleBlockPluginInterface.php b/core/lib/Drupal/Core/Block/TitleBlockPluginInterface.php new file mode 100644 index 0000000..19ab275 --- /dev/null +++ b/core/lib/Drupal/Core/Block/TitleBlockPluginInterface.php @@ -0,0 +1,30 @@ + 'page_title', + // The page title: either a string for plain titles or a render array for + // formatted titles. + '#title' => NULL, + ]; + } + +} diff --git a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php index 5cfa312..935c34d 100644 --- a/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php +++ b/core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php @@ -192,11 +192,18 @@ public function renderResponse(array $main_content, Request $request, RouteMatch * If the selected display variant does not implement PageVariantInterface. */ protected function prepare(array $main_content, Request $request, RouteMatchInterface $route_match) { + // Determine the title: use the title provided by the main content if any, + // otherwise get it from the routing information. + $get_title = function (array $main_content) use ($request, $route_match) { + return isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); + }; + // If the _controller result already is #type => page, // we have no work to do: The "main content" already is an entire "page" // (see html.html.twig). if (isset($main_content['#type']) && $main_content['#type'] === 'page') { $page = $main_content; + $title = $get_title($page); } // Otherwise, render it as the main content of a #type => page, by selecting // page display variant to do that and building that page display variant. @@ -220,6 +227,9 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte // missing for controllers whose entire returned render array is // render cached. $main_content['#cache_properties'][] = '#title'; + // Retain #contextual_links, otherwise main content that has + // associated contextual links would be missing. + $main_content['#cache_properties'][] = '#contextual_links'; } return $this->renderer->render($main_content, FALSE); }); @@ -228,6 +238,8 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte ]; } + $title = $get_title($main_content); + // Instantiate the page display, and give it the main content. $page_display = $this->displayVariantManager->createInstance($variant_id); if (!$page_display instanceof PageVariantInterface) { @@ -235,6 +247,7 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte } $page_display ->setMainContent($main_content) + ->setTitle($title) ->setConfiguration($event->getPluginConfiguration()); // Generate a #type => page render array using the page display variant, @@ -258,10 +271,6 @@ protected function prepare(array $main_content, Request $request, RouteMatchInte // Allow hooks to add attachments to $page['#attached']. $this->invokePageAttachmentHooks($page); - // Determine the title: use the title provided by the main content if any, - // otherwise get it from the routing information. - $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); - return [$page, $title]; } diff --git a/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php index baef325..987cfaa 100644 --- a/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php +++ b/core/lib/Drupal/Core/Render/Plugin/DisplayVariant/SimplePageVariant.php @@ -28,6 +28,13 @@ class SimplePageVariant extends VariantBase implements PageVariantInterface { protected $mainContent; /** + * The page title: a string (plain title) or a render array (formatted title). + * + * @var string|array + */ + protected $title = ''; + + /** * {@inheritdoc} */ public function setMainContent(array $main_content) { @@ -38,9 +45,22 @@ public function setMainContent(array $main_content) { /** * {@inheritdoc} */ + public function setTitle($title) { + $this->title = $title; + return $this; + } + + /** + * {@inheritdoc} + */ public function build() { $build = [ 'content' => [ + 'page_title' => [ + '#type' => 'page_title', + '#title' => $this->title, + '#weight' => -900, + ], 'main_content' => $this->mainContent, 'messages' => [ '#type' => 'status_messages', @@ -48,6 +68,9 @@ public function build() { ], ], ]; + // Assign the main content container theme wrapper to the main content, to + // ensure contextual links on the main content work as expected. + $build['content']['main_content']['#theme_wrappers'][] = 'container__main_content'; return $build; } diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php index 9a582352..80f52c1 100644 --- a/core/modules/block/src/BlockViewBuilder.php +++ b/core/modules/block/src/BlockViewBuilder.php @@ -8,6 +8,7 @@ namespace Drupal\block; use Drupal\Core\Block\MainContentBlockPluginInterface; +use Drupal\Core\Block\TitleBlockPluginInterface; use Drupal\Core\Cache\Cache; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityManagerInterface; @@ -104,7 +105,7 @@ public function viewMultiple(array $entities = array(), $view_mode = 'full', $la // Allow altering of cacheability metadata or setting #create_placeholder. $this->moduleHandler->alter(['block_build', "block_build_" . $plugin->getBaseId()], $build[$entity_id], $plugin); - if ($plugin instanceof MainContentBlockPluginInterface) { + if ($plugin instanceof MainContentBlockPluginInterface || $plugin instanceof TitleBlockPluginInterface) { // Immediately build a #pre_render-able block, since this block cannot // be built lazily. $build[$entity_id] += static::buildPreRenderableBlock($entity, $this->moduleHandler()); diff --git a/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php b/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php index 650cf78..d3f73f6 100644 --- a/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php +++ b/core/modules/block/src/Plugin/DisplayVariant/BlockPageVariant.php @@ -9,6 +9,7 @@ use Drupal\block\BlockRepositoryInterface; use Drupal\Core\Block\MainContentBlockPluginInterface; +use Drupal\Core\Block\TitleBlockPluginInterface; use Drupal\Core\Block\MessagesBlockPluginInterface; use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Display\PageVariantInterface; @@ -64,6 +65,13 @@ class BlockPageVariant extends VariantBase implements PageVariantInterface, Cont protected $mainContent = []; /** + * The page title: a string (plain title) or a render array (formatted title). + * + * @var string|array + */ + protected $title = ''; + + /** * Constructs a new BlockPageVariant. * * @param array $configuration @@ -111,9 +119,19 @@ public function setMainContent(array $main_content) { /** * {@inheritdoc} */ + public function setTitle($title) { + $this->title = $title; + return $this; + } + + /** + * {@inheritdoc} + */ public function build() { - // Track whether blocks showing the main content and messages are displayed. + // Track whether blocks showing the main content, title and messages are + // displayed. $main_content_block_displayed = FALSE; + $title_block_displayed = FALSE; $messages_block_displayed = FALSE; $build = [ @@ -131,6 +149,10 @@ public function build() { $block_plugin->setMainContent($this->mainContent); $main_content_block_displayed = TRUE; } + elseif ($block_plugin instanceof TitleBlockPluginInterface) { + $block_plugin->setTitle($this->title); + $title_block_displayed = TRUE; + } elseif ($block_plugin instanceof MessagesBlockPluginInterface) { $messages_block_displayed = TRUE; } @@ -138,8 +160,9 @@ public function build() { // The main content block cannot be cached: it is a placeholder for the // render array returned by the controller. It should be rendered as-is, - // with other placed blocks "decorating" it. - if ($block_plugin instanceof MainContentBlockPluginInterface) { + // with other placed blocks "decorating" it. Analogous reasoning for the + // title block. + if ($block_plugin instanceof MainContentBlockPluginInterface || $block_plugin instanceof TitleBlockPluginInterface) { unset($build[$region][$key]['#cache']['keys']); } } @@ -155,6 +178,9 @@ public function build() { // the main content they came for. if (!$main_content_block_displayed) { $build['content']['system_main'] = $this->mainContent; + // Assign the main content container theme wrapper to the main content, to + // ensure contextual links on the main content work as expected. + $build['content']['system_main']['#theme_wrappers'][] = 'container__main_content'; } // If no block displays status messages, still render them. @@ -165,6 +191,15 @@ public function build() { ]; } + // Analogously for the page title. + if (!$title_block_displayed) { + $build['content']['page_title'] = [ + '#type' => 'page_title', + '#title' => $this->title, + '#weight' => -900, + ]; + } + // The access results' cacheability is currently added to the top level of the // render array. This is done to prevent issues with empty regions being // displayed. diff --git a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php index 147e64a..e54f9c1 100644 --- a/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php +++ b/core/modules/block/tests/src/Unit/Plugin/DisplayVariant/BlockPageVariantTest.php @@ -74,28 +74,32 @@ public function setUpDisplayVariant($configuration = array(), $definition = arra public function providerBuild() { $blocks_config = array( 'block1' => array( - // region, is main content block, is messages block - 'top', FALSE, FALSE, + // region, is main content block, is messages block, is title block + 'top', FALSE, FALSE, FALSE, ), // Test multiple blocks in the same region. 'block2' => array( - 'bottom', FALSE, FALSE, + 'bottom', FALSE, FALSE, FALSE, ), 'block3' => array( - 'bottom', FALSE, FALSE, + 'bottom', FALSE, FALSE, FALSE, ), // Test a block implementing MainContentBlockPluginInterface. 'block4' => array( - 'center', TRUE, FALSE, + 'center', TRUE, FALSE, FALSE, ), // Test a block implementing MessagesBlockPluginInterface. 'block5' => array( - 'center', FALSE, TRUE, + 'center', FALSE, TRUE, FALSE, + ), + // Test a block implementing TitleBlockPluginInterface. + 'block7' => array( + 'center', FALSE, FALSE, TRUE, ), ); $test_cases = []; - $test_cases[] = [$blocks_config, 5, + $test_cases[] = [$blocks_config, 6, [ '#cache' => [ 'tags' => [ @@ -113,6 +117,7 @@ public function providerBuild() { 'center' => [ 'block4' => [], 'block5' => [], + 'block7' => [], '#sorted' => TRUE, ], 'bottom' => [ @@ -123,7 +128,7 @@ public function providerBuild() { ], ]; unset($blocks_config['block5']); - $test_cases[] = [$blocks_config, 4, + $test_cases[] = [$blocks_config, 5, [ '#cache' => [ 'tags' => [ @@ -139,6 +144,7 @@ public function providerBuild() { ], 'center' => [ 'block4' => [], + 'block7' => [], '#sorted' => TRUE, ], 'bottom' => [ @@ -146,8 +152,8 @@ public function providerBuild() { 'block3' => [], '#sorted' => TRUE, ], - // The messages are rendered via the fallback in case there is no block - // rendering the main content. + // The messages and title are rendered via the fallback in case there is + // no block rendering the main content. 'content' => [ 'messages' => [ '#weight' => -1000, @@ -157,6 +163,7 @@ public function providerBuild() { ], ]; unset($blocks_config['block4']); + unset($blocks_config['block7']); $test_cases[] = [$blocks_config, 3, [ '#cache' => [ @@ -176,14 +183,22 @@ public function providerBuild() { 'block3' => [], '#sorted' => TRUE, ], - // The main content & messages are rendered via the fallback in case - // there are no blocks rendering them. + // The main content, messages and title are rendered via the fallback in + // case there are no blocks rendering them. 'content' => [ - 'system_main' => ['#markup' => 'Hello kittens!'], + 'system_main' => [ + '#markup' => 'Hello kittens!', + '#theme_wrappers' => ['container__main_content'], + ], 'messages' => [ '#weight' => -1000, '#type' => 'status_messages', ], + 'page_title' => [ + '#type' => 'page_title', + '#title' => 'Hi cats!', + '#weight' => -900, + ], ], ], ]; @@ -200,11 +215,13 @@ public function providerBuild() { public function testBuild(array $blocks_config, $visible_block_count, array $expected_render_array) { $display_variant = $this->setUpDisplayVariant(); $display_variant->setMainContent(['#markup' => 'Hello kittens!']); + $display_variant->setTitle('Hi cats!'); $blocks = ['top' => [], 'center' => [], 'bottom' => []]; $block_plugin = $this->getMock('Drupal\Core\Block\BlockPluginInterface'); $main_content_block_plugin = $this->getMock('Drupal\Core\Block\MainContentBlockPluginInterface'); $messages_block_plugin = $this->getMock('Drupal\Core\Block\MessagesBlockPluginInterface'); + $title_block_plugin = $this->getMock('Drupal\Core\Block\TitleBlockPluginInterface'); foreach ($blocks_config as $block_id => $block_config) { $block = $this->getMock('Drupal\block\BlockInterface'); $block->expects($this->any()) @@ -212,7 +229,7 @@ public function testBuild(array $blocks_config, $visible_block_count, array $exp ->willReturn([]); $block->expects($this->atLeastOnce()) ->method('getPlugin') - ->willReturn($block_config[1] ? $main_content_block_plugin : ($block_config[2] ? $messages_block_plugin : $block_plugin)); + ->willReturn($block_config[1] ? $main_content_block_plugin : ($block_config[2] ? $messages_block_plugin : ($block_config[3] ? $title_block_plugin : $block_plugin))); $blocks[$block_config[0]][$block_id] = $block; } $this->blockViewBuilder->expects($this->exactly($visible_block_count)) @@ -239,6 +256,7 @@ public function testBuildWithoutMainContent() { $this->blockRepository->expects($this->once()) ->method('getVisibleBlocksPerRegion') ->willReturn([]); + $display_variant->setTitle('Hi llamas!'); $expected = [ '#cache' => [ @@ -249,11 +267,18 @@ public function testBuildWithoutMainContent() { 'max-age' => -1, ], 'content' => [ - 'system_main' => [], + 'system_main' => [ + '#theme_wrappers' => ['container__main_content'], + ], 'messages' => [ '#weight' => -1000, '#type' => 'status_messages', ], + 'page_title' => [ + '#type' => 'page_title', + '#title' => 'Hi llamas!', + '#weight' => -900, + ], ], ]; $this->assertSame($expected, $display_variant->build()); diff --git a/core/modules/comment/src/Tests/CommentTestBase.php b/core/modules/comment/src/Tests/CommentTestBase.php index 12ea894..75efbd4 100644 --- a/core/modules/comment/src/Tests/CommentTestBase.php +++ b/core/modules/comment/src/Tests/CommentTestBase.php @@ -188,14 +188,22 @@ public function postComment($entity, $comment, $subject = '', $contact = NULL, $ */ function commentExists(CommentInterface $comment = NULL, $reply = FALSE) { if ($comment) { - $regex = '!' . ($reply ? '
(.*?)' : ''); - $regex .= 'getSubject() . '(.*?)'; - $regex .= $comment->comment_body->value . '(.*?)'; - $regex .= ($reply ? '\s
(.*?)' : ''); - $regex .= '!s'; - - return (boolean) preg_match($regex, $this->getRawContent()); + $comment_element = $this->cssSelect('.comment-wrapper ' . ($reply ? '.indented ' : '') . '#comment-' . $comment->id() . ' ~ article'); + if (empty($comment_element)) { + return FALSE; + } + + $comment_title = $comment_element[0]->xpath('div/h3/a'); + if (empty($comment_title) || ((string)$comment_title[0]) !== $comment->getSubject()) { + return FALSE; + } + + $comment_body = $comment_element[0]->xpath('div/div/p'); + if (empty($comment_body) || ((string)$comment_body[0]) !== $comment->comment_body->value) { + return FALSE; + } + + return TRUE; } else { return FALSE; diff --git a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php index 58f8fde..4b54ae2 100644 --- a/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php +++ b/core/modules/page_cache/src/Tests/PageCacheTagsIntegrationTest.php @@ -106,6 +106,7 @@ function testPageCacheTags() { 'config:block.block.bartik_messages', 'config:block.block.bartik_local_actions', 'config:block.block.bartik_local_tasks', + 'config:block.block.bartik_page_title', 'node_view', 'node:' . $node_1->id(), 'user:' . $author_1->id(), @@ -143,6 +144,7 @@ function testPageCacheTags() { 'config:block.block.bartik_messages', 'config:block.block.bartik_local_actions', 'config:block.block.bartik_local_tasks', + 'config:block.block.bartik_page_title', 'node_view', 'node:' . $node_2->id(), 'user:' . $author_2->id(), diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index be83839..ec49ea1 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -298,9 +298,9 @@ function shortcut_preprocess_block(&$variables) { } /** - * Implements hook_preprocess_HOOK() for page templates. + * Implements hook_preprocess_HOOK() for page title templates. */ -function shortcut_preprocess_page(&$variables) { +function shortcut_preprocess_page_title(&$variables) { // Only display the shortcut link if the user has the ability to edit // shortcuts and if the page's actual content is being shown (for example, // we do not want to display it on "access denied" or "page not found" @@ -309,9 +309,12 @@ function shortcut_preprocess_page(&$variables) { $link = Url::fromRouteMatch(\Drupal::routeMatch())->getInternalPath(); $route_match = \Drupal::routeMatch(); + // Replicate template_preprocess_html()'s processing to get the title in + // string form, so we can set the default name for the shortcut. + $name = render($variables['title']); $query = array( 'link' => $link, - 'name' => $variables['title'], + 'name' => $name, ); $shortcut_set = shortcut_current_displayed_set(); diff --git a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php index 5aeef20..5e8e5fa 100644 --- a/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php +++ b/core/modules/system/src/Tests/Entity/EntityViewControllerTest.php @@ -47,7 +47,7 @@ protected function setUp() { */ function testEntityViewController() { $get_label_markup = function($label) { - return '

+ return '

' . $label . '

'; }; diff --git a/core/modules/system/src/Tests/Installer/InstallerTest.php b/core/modules/system/src/Tests/Installer/InstallerTest.php index b17e3e7..debb891 100644 --- a/core/modules/system/src/Tests/Installer/InstallerTest.php +++ b/core/modules/system/src/Tests/Installer/InstallerTest.php @@ -40,6 +40,41 @@ protected function setUpLanguage() { // metatags as expected to the first page of the installer. $this->assertRaw('core/themes/seven/css/components/buttons.css'); $this->assertRaw(''); + + // Assert that the expected title is present. + $this->assertEqual('Choose language', $this->cssSelect('main h1')[0]); + parent::setUpLanguage(); } + + /** + * {@inheritdoc} + */ + protected function setUpProfile() { + // Assert that the expected title is present. + $this->assertEqual('Select an installation profile', $this->cssSelect('main h1')[0]); + + parent::setUpProfile(); + } + + /** + * {@inheritdoc} + */ + protected function setUpSettings() { + // Assert that the expected title is present. + $this->assertEqual('Database configuration', $this->cssSelect('main h1')[0]); + + parent::setUpSettings(); + } + + /** + * {@inheritdoc} + */ + protected function setUpSite() { + // Assert that the expected title is present. + $this->assertEqual('Configure site', $this->cssSelect('main h1')[0]); + + parent::setUpSite(); + } + } diff --git a/core/modules/system/src/Tests/System/PageTitleTest.php b/core/modules/system/src/Tests/System/PageTitleTest.php index 73ef4bd..847d2d4 100644 --- a/core/modules/system/src/Tests/System/PageTitleTest.php +++ b/core/modules/system/src/Tests/System/PageTitleTest.php @@ -105,14 +105,14 @@ public function testRoutingTitle() { $this->drupalGet('test-render-title'); $this->assertTitle('Foo | Drupal'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual('Foo', (string) $result[0]); // Test forms $this->drupalGet('form-test/object-builder'); $this->assertTitle('Test dynamic title | Drupal'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual('Test dynamic title', (string) $result[0]); // Set some custom translated strings. @@ -125,14 +125,14 @@ public function testRoutingTitle() { $this->drupalGet('test-page-static-title'); $this->assertTitle('Static title translated | Drupal'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual('Static title translated', (string) $result[0]); // Test the dynamic '_title_callback' route option. $this->drupalGet('test-page-dynamic-title'); $this->assertTitle('Dynamic title | Drupal'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual('Dynamic title', (string) $result[0]); // Ensure that titles are cacheable and are escaped normally if the diff --git a/core/modules/system/src/Tests/System/SiteMaintenanceTest.php b/core/modules/system/src/Tests/System/SiteMaintenanceTest.php index 54ab8b7..85c4ceb 100644 --- a/core/modules/system/src/Tests/System/SiteMaintenanceTest.php +++ b/core/modules/system/src/Tests/System/SiteMaintenanceTest.php @@ -67,10 +67,13 @@ protected function testSiteMaintenance() { // Logout and verify that offline message is displayed. $this->drupalLogout(); $this->drupalGet(''); + $this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]); $this->assertText($offline_message); $this->drupalGet('node'); + $this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]); $this->assertText($offline_message); $this->drupalGet('user/register'); + $this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]); $this->assertText($offline_message); // Verify that user is able to log in. @@ -103,6 +106,7 @@ protected function testSiteMaintenance() { // Logout and verify that custom site offline message is displayed. $this->drupalLogout(); $this->drupalGet(''); + $this->assertEqual('Site under maintenance', $this->cssSelect('main h1')[0]); $this->assertRaw($offline_message, 'Found the site offline message.'); // Verify that custom site offline message is not displayed on user/password. diff --git a/core/modules/system/src/Tests/Update/PageTitleConvertedIntoBlockUpdateTest.php b/core/modules/system/src/Tests/Update/PageTitleConvertedIntoBlockUpdateTest.php new file mode 100644 index 0000000..1602a52 --- /dev/null +++ b/core/modules/system/src/Tests/Update/PageTitleConvertedIntoBlockUpdateTest.php @@ -0,0 +1,82 @@ +databaseDumpFiles = [ + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.bare.standard.php.gz', + __DIR__ . '/../../../../system/tests/fixtures/update/drupal-8.page-title-into-block-2476947.php', + ]; + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + // @todo Remove in https://www.drupal.org/node/2568069. + /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */ + $theme_handler = \Drupal::service('theme_handler'); + $theme_handler->refreshInfo(); + } + + /** + * Tests that page title is being converted into a block. + */ + public function testUpdateHookN() { + $this->runUpdates(); + + /** @var \Drupal\block\BlockInterface $block_storage */ + $block_storage = \Drupal::entityManager()->getStorage('block'); + + $this->assertRaw('Because your site has custom theme(s) installed, we have placed the page title block in the content region. Please manually review the block configuration and remove the page title variables from your page templates.'); + + // Disable maintenance mode. + // @todo Can be removed once maintenance mode is automatically turned off + // after updates in https://www.drupal.org/node/2435135. + \Drupal::state()->set('system.maintenance_mode', FALSE); + + // We finished updating so we can login the user now. + $this->drupalLogin($this->rootUser); + + $page = Node::create([ + 'type' => 'page', + 'title' => 'Page node', + ]); + $page->save(); + + // Page title is visible on the home page. + $this->drupalGet('/node'); + $this->assertRaw('page-title'); + + // Page title is visible on a node page. + $this->drupalGet('node/' . $page->id()); + $this->assertRaw('page-title'); + + $this->drupalGet('admin/structure/block/list/bartik'); + + /** @var \Drupal\Core\Config\StorageInterface $config_storage */ + $config_storage = \Drupal::service('config.storage'); + $this->assertTrue($config_storage->exists('block.block.test_theme_page_title'), 'Page title block has been created for the custom theme.'); + } + +} diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 6155a6c..c59765e 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -1468,16 +1468,16 @@ function system_update_8005() { default: $custom_themes_installed = TRUE; - $name = sprintf('block.block.%s_local_actions', $theme_name); + $name = 'block.block.' . $theme_name . '_local_actions'; $values = [ - 'id' => sprintf('%s_local_actions', $theme_name), + 'id' => $theme_name . '_local_actions', 'weight' => -10, ] + $local_actions_default_settings; _system_update_create_block($name, $theme_name, $values); $name = sprintf('block.block.%s_local_tasks', $theme_name); $values = [ - 'id' => sprintf('%s_local_tasks', $theme_name), + 'id' => $theme_name . '_local_tasks', 'weight' => -20, ] + $tabs_default_settings; _system_update_create_block($name, $theme_name, $values); @@ -1642,5 +1642,88 @@ function system_update_8007() { } /** + * Place page title blocks in every theme. + */ +function system_update_8008() { + // When block module is not installed, there is nothing that could be done + // except showing a warning. + if (!\Drupal::moduleHandler()->moduleExists('block')) { + return t('Block module is not enabled. The page title has been converted to a block, but default page title markup will still display at the top of the main content area.'); + } + + /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */ + $theme_handler = \Drupal::service('theme_handler'); + $custom_themes_installed = FALSE; + $message = NULL; + $langcode = \Drupal::service('language_manager')->getCurrentLanguage()->getId(); + + $page_title_default_settings = [ + 'plugin' => 'page_title_block', + 'region' => 'content', + 'settings.label' => 'Page title', + 'settings.label_display' => 0, + 'visibility' => [], + 'weight' => -50, + 'langcode' => $langcode, + ]; + foreach ($theme_handler->listInfo() as $theme) { + $theme_name = $theme->getName(); + switch ($theme_name) { + case 'bartik': + $name = 'block.block.bartik_page_title'; + $values = [ + 'id' => 'bartik_page_title', + ] + $page_title_default_settings; + _system_update_create_block($name, $theme_name, $values); + break; + + case 'stark': + $name = 'block.block.stark_page_title'; + $values = [ + 'id' => 'stark_branding', + 'region' => 'content', + ] + $page_title_default_settings; + _system_update_create_block($name, $theme_name, $values); + break; + + case 'seven': + $name = 'block.block.seven_page_title'; + $values = [ + 'id' => 'seven_page_title', + 'region' => 'header', + ] + $page_title_default_settings; + _system_update_create_block($name, $theme_name, $values); + break; + + case 'classy': + $name = 'block.block.classy_page_title'; + $values = [ + 'id' => 'classy_page_title', + 'region' => 'content', + ] + $page_title_default_settings; + _system_update_create_block($name, $theme_name, $values); + break; + + default: + $custom_themes_installed = TRUE; + $name = sprintf('block.block.%s_page_title', $theme_name); + $values = [ + 'id' => sprintf('%s_page_title', $theme_name), + 'region' => 'content', + 'weight' => '-50', + ] + $page_title_default_settings; + _system_update_create_block($name, $theme_name, $values); + break; + } + } + + if ($custom_themes_installed) { + $message = t('Because your site has custom theme(s) installed, we have placed the page title block in the content region. Please manually review the block configuration and remove the page title variables from your page templates.'); + } + + return $message; +} + +/** * @} End of "addtogroup updates-8.0.0-beta". */ diff --git a/core/modules/system/system.module b/core/modules/system/system.module index a8cc12d..145ffef 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -213,6 +213,9 @@ function system_theme() { 'variables' => array('menu_items' => NULL), 'file' => 'system.admin.inc', ), + 'container__main_content' => array( + 'base hook' => 'container', + ), )); } @@ -1396,15 +1399,6 @@ function system_entity_type_build(array &$entity_types) { } /** - * Implements hook_block_view_BASE_BLOCK_ID_alter(). - */ -function system_block_view_system_main_block_alter(array &$build, BlockPluginInterface $block) { - // Contextual links on the system_main block would basically duplicate the - // tabs/local tasks, so reduce the clutter. - unset($build['#contextual_links']); -} - -/** * Implements hook_path_update(). */ function system_path_update() { diff --git a/core/modules/system/templates/container--main-content.html.twig b/core/modules/system/templates/container--main-content.html.twig new file mode 100644 index 0000000..ad841a9 --- /dev/null +++ b/core/modules/system/templates/container--main-content.html.twig @@ -0,0 +1,12 @@ +{# +/** + * @file + * Main content container. + * + * Unlike container.html.twig, this also prints title_suffix, to allow the main + * content to show a contextual link. + * + * @ingroup themeable + */ +#} +{{ title_suffix }}{{ children }} diff --git a/core/modules/system/templates/page-title.html.twig b/core/modules/system/templates/page-title.html.twig new file mode 100644 index 0000000..2b994bc --- /dev/null +++ b/core/modules/system/templates/page-title.html.twig @@ -0,0 +1,23 @@ +{# +/** + * @file + * Default theme implementation for page titles. + * + * Available variables: + * - title_attributes: HTML attributes for the page title element. + * - 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. + * + * @see template_preprocess_page_title() + * + * @ingroup themeable + */ +#} +{{ title_prefix }} +{% if title %} + {{ title }} +{% endif %} +{{ title_suffix }} diff --git a/core/modules/system/templates/page.html.twig b/core/modules/system/templates/page.html.twig index d9532bf..897ffef 100644 --- a/core/modules/system/templates/page.html.twig +++ b/core/modules/system/templates/page.html.twig @@ -26,11 +26,6 @@ * slogan has been disabled in theme settings. * * Page content (in order of occurrence in the default page.html.twig): - * - 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. * - messages: Status and error messages. Should be displayed prominently. * - 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 @@ -74,12 +69,6 @@
{# link is in html.html.twig #}
- - {{ title_prefix }} - {% if title %} -

{{ title }}

- {% endif %} - {{ title_suffix }} {{ page.content }}
{# /.layout-content #} diff --git a/core/modules/system/tests/fixtures/update/block.block.testfor2476947.yml b/core/modules/system/tests/fixtures/update/block.block.testfor2476947.yml new file mode 100644 index 0000000..ff067d6 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/block.block.testfor2476947.yml @@ -0,0 +1,20 @@ +uuid: 6d4df0fb-e985-4798-b400-f5242d95f0f7 +langcode: en +status: true +dependencies: + theme: + - bartik +id: bartik_page_title +theme: bartik +region: content +weight: -50 +provider: null +plugin: page_title_block +settings: + id: page_title_block + label: 'Page title' + provider: core + label_display: '0' + cache: + max_age: -1 +visibility: { } diff --git a/core/modules/system/tests/fixtures/update/drupal-8.page-title-into-block-2476947.php b/core/modules/system/tests/fixtures/update/drupal-8.page-title-into-block-2476947.php new file mode 100644 index 0000000..ae3e777 --- /dev/null +++ b/core/modules/system/tests/fixtures/update/drupal-8.page-title-into-block-2476947.php @@ -0,0 +1,60 @@ +insert('config') + ->fields([ + 'collection', + 'name', + 'data', + ]) + ->values([ + 'collection' => '', + 'name' => 'block.block.' . $block_config['id'], + 'data' => serialize($block_config), + ]) + ->execute(); +} + +// Update the config entity query "index". +$existing_blocks = $connection->select('key_value') + ->fields('key_value', ['value']) + ->condition('collection', 'config.entity.key_store.block') + ->condition('name', 'theme:bartik') + ->execute() + ->fetchField(); +$existing_blocks = unserialize($existing_blocks); + +$connection->update('key_value') + ->fields([ + 'value' => serialize(array_merge($existing_blocks, ['block.block.bartik_page_title'])) + ]) + ->condition('collection', 'config.entity.key_store.block') + ->condition('name', 'theme:bartik') + ->execute(); + +// Enable test theme. +$extensions = $connection->select('config') + ->fields('config', ['data']) + ->condition('name', 'core.extension') + ->execute() + ->fetchField(); +$extensions = unserialize($extensions); +$connection->update('config') + ->fields([ + 'data' => serialize(array_merge_recursive($extensions, ['theme' => ['test_theme' => 0]])) + ]) + ->condition('name', 'core.extension') + ->execute(); diff --git a/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php b/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php index 2057272..fd903af 100644 --- a/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php +++ b/core/modules/system/tests/modules/display_variant_test/src/Plugin/DisplayVariant/TestDisplayVariant.php @@ -28,6 +28,13 @@ class TestDisplayVariant extends VariantBase implements PageVariantInterface { protected $mainContent = []; /** + * The page title: a string (plain title) or a render array (formatted title). + * + * @var string|array + */ + protected $title = ''; + + /** * {@inheritdoc} */ public function setMainContent(array $main_content) { @@ -38,6 +45,14 @@ public function setMainContent(array $main_content) { /** * {@inheritdoc} */ + public function setTitle($title) { + $this->title = $title; + return $this; + } + + /** + * {@inheritdoc} + */ public function build() { $config = $this->getConfiguration(); if (empty($config['required_configuration'])) { diff --git a/core/modules/user/src/Tests/Views/RolesRidArgumentTest.php b/core/modules/user/src/Tests/Views/RolesRidArgumentTest.php index 642a691..ade4e91 100644 --- a/core/modules/user/src/Tests/Views/RolesRidArgumentTest.php +++ b/core/modules/user/src/Tests/Views/RolesRidArgumentTest.php @@ -26,13 +26,13 @@ class RolesRidArgumentTest extends UserTestBase { * Tests the generated title of a user: roles argument. */ public function testArgumentTitle() { - $role_id = $this->createRole([], 'markup_role_name', 'Role name with markup'); + $role_id = $this->createRole([], 'markup_role_name', 'Role name with markup'); $user = $this->createUser(); $user->addRole($role_id); $user->save(); $this->drupalGet('/user_roles_rid_test/markup_role_name'); - $this->assertEscaped('Role name with markup'); + $this->assertRaw('Role name with markupalert("test")'); } } diff --git a/core/modules/views/js/views-contextual.js b/core/modules/views/js/views-contextual.js deleted file mode 100644 index e6586eb..0000000 --- a/core/modules/views/js/views-contextual.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file - * Javascript related to contextual links. - */ - -(function ($) { - - "use strict"; - - /** - * Attaches contextual region classes to views elements. - * - * @type {Drupal~behavior} - * - * @prop {Drupal~behaviorAttach} attach - * Adds class `contextual-region` to views elements. - */ - Drupal.behaviors.viewsContextualLinks = { - attach: function (context) { - var id = $('body').attr('data-views-page-contextual-id'); - - $('[data-contextual-id="' + id + '"]') - .closest(':has(.view)') - .addClass('contextual-region'); - } - }; - -})(jQuery); diff --git a/core/modules/views/src/Routing/ViewPageController.php b/core/modules/views/src/Routing/ViewPageController.php index cf3ae53..592b7d1 100644 --- a/core/modules/views/src/Routing/ViewPageController.php +++ b/core/modules/views/src/Routing/ViewPageController.php @@ -60,6 +60,8 @@ public function handle($view_id, $display_id, RouteMatchInterface $route_match) $build = $class::buildBasicRenderable($view_id, $display_id, $args, $route); Page::setPageRenderArray($build); + views_add_contextual_links($build, 'page', $display_id, $build); + return $build; } } diff --git a/core/modules/views/src/Tests/Plugin/DisabledDisplayTest.php b/core/modules/views/src/Tests/Plugin/DisabledDisplayTest.php index e9052b4..0b6faec 100644 --- a/core/modules/views/src/Tests/Plugin/DisabledDisplayTest.php +++ b/core/modules/views/src/Tests/Plugin/DisabledDisplayTest.php @@ -58,7 +58,7 @@ public function testDisabledDisplays() { // Enabled page display should return content. $this->drupalGet('test-disabled-display'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual($result[0], 'test_disabled_display', 'The enabled page_1 display is accessible.'); // Disabled page view should 404. @@ -77,7 +77,7 @@ public function testDisabledDisplays() { // Check that the originally disabled page_2 display is now enabled. $this->drupalGet('test-disabled-display-2'); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertEqual($result[0], 'test_disabled_display', 'The enabled page_2 display is accessible.'); // Disable each disabled display and save the view. diff --git a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php index 4604406..87bee46 100644 --- a/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php +++ b/core/modules/views/tests/src/Unit/Routing/ViewPageControllerTest.php @@ -5,7 +5,7 @@ * Contains \Drupal\Tests\views\Unit\Routing\ViewPageControllerTest. */ -namespace Drupal\Tests\views\Unit\Routing; +namespace Drupal\Tests\views\Unit\Routing { use Drupal\Core\Routing\RouteMatch; use Drupal\Tests\UnitTestCase; @@ -181,3 +181,13 @@ public function testHandleWithArgumentsOnOverriddenRouteWithUpcasting() { } } + +} + +namespace { + // @todo replace views_add_contextual_links() + if (!function_exists('views_add_contextual_links')) { + function views_add_contextual_links() { + } + } +} diff --git a/core/modules/views/views.libraries.yml b/core/modules/views/views.libraries.yml index 03efb2c..640492d 100644 --- a/core/modules/views/views.libraries.yml +++ b/core/modules/views/views.libraries.yml @@ -16,12 +16,3 @@ views.ajax: - core/jquery.once - core/jquery.form - core/drupal.ajax - -views.contextual-links: - version: VERSION - js: - # Ensure to run before contextual/drupal.contextual-links. - js/views-contextual.js: { weight: -10 } - dependencies: - - core/jquery - - core/drupal diff --git a/core/modules/views/views.module b/core/modules/views/views.module index 22424a1..fd7f33a 100644 --- a/core/modules/views/views.module +++ b/core/modules/views/views.module @@ -302,39 +302,6 @@ function views_theme_suggestions_container_alter(array &$suggestions, array $var } /** - * Implements MODULE_preprocess_HOOK(). - */ -function views_preprocess_html(&$variables) { - if (!\Drupal::moduleHandler()->moduleExists('contextual')) { - return; - } - - // If the main content of this page contains a view, attach its contextual - // links to the overall page array. This allows them to be rendered directly - // next to the page title. - if ($render_array = Page::getPageRenderArray()) { - views_add_contextual_links($variables['page'], 'page', $render_array['#display_id'], $render_array); - } - - // If the page contains a view as its main content, contextual links may have - // been attached to the page as a whole; for example, by - // views_page_display_pre_render(). - // This allows them to be associated with the page and rendered by default - // next to the page title (which we want). However, it also causes the - // Contextual Links module to treat the wrapper for the entire page (i.e., - // the tag) as the HTML element that these contextual links are - // associated with. This we don't want; for better visual highlighting, we - // prefer a smaller region to be chosen. The region we prefer differs from - // theme to theme and depends on the details of the theme's markup in - // page.html.twig, so we can only find it using JavaScript. We therefore - // remove the "contextual-region" class from the tag here and add - // JavaScript that will insert it back in the correct place. - if (!empty($variables['page']['#views_contextual_links'])) { - $variables['attributes']['data-views-page-contextual-id'] = _contextual_links_to_id($variables['page']['#contextual_links']); - } -} - -/** * Adds contextual links associated with a view display to a renderable array. * * This function should be called when a view is being rendered in a particular @@ -470,9 +437,6 @@ function views_add_contextual_links(&$render_element, $location, $display_id, ar // user that may use contextual links, attach Views' contextual links // JavaScript. $render_element['#cache']['contexts'][] = 'user.permissions'; - if ($location === 'page' && $render_element['#type'] === 'page' && \Drupal::currentUser()->hasPermission('access contextual links')) { - $render_element['#attached']['library'][] = 'views/views.contextual-links'; - } } } } diff --git a/core/modules/views_ui/src/Tests/DisplayTest.php b/core/modules/views_ui/src/Tests/DisplayTest.php index 20667de..1f13508 100644 --- a/core/modules/views_ui/src/Tests/DisplayTest.php +++ b/core/modules/views_ui/src/Tests/DisplayTest.php @@ -180,6 +180,8 @@ public function testPageContextualLinks() { $view->enable()->save(); $this->container->get('router.builder')->rebuildIfNeeded(); + // When no "main content" block is placed, we find a contextual link + // placeholder for editing just the view. $this->drupalGet('test-display'); $id = 'entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en'; // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() @@ -192,6 +194,14 @@ public function testPageContextualLinks() { $this->assertResponse(200); $json = Json::decode($response); $this->assertIdentical($json[$id], ''); + + // When a "main content" is placed, we find a contexutal link placeholder + // for both configuring the block and editing the view. + $this->drupalPlaceBlock('system_main_block', ['id' => 'main_content']); + $this->drupalGet('test-display'); + $id = 'block:block=main_content:langcode=en|entity.view.edit_form:view=test_display:location=page&name=test_display&display_id=page_1&langcode=en'; + // @see \Drupal\contextual\Tests\ContextualDynamicContextTest:assertContextualLinkPlaceHolder() + $this->assertRaw(' $id)) . '>', format_string('Contextual link placeholder with id @id exists.', array('@id' => $id))); } /** diff --git a/core/modules/views_ui/src/Tests/HandlerTest.php b/core/modules/views_ui/src/Tests/HandlerTest.php index c53ddd7..6eef010 100644 --- a/core/modules/views_ui/src/Tests/HandlerTest.php +++ b/core/modules/views_ui/src/Tests/HandlerTest.php @@ -155,7 +155,7 @@ public function testBrokenHandlers() { $this->assertIdentical((string) $result[0], $text, 'Ensure the broken handler text was found.'); $this->drupalGet($href); - $result = $this->xpath('//h1'); + $result = $this->xpath('//h1[@class="page-title"]'); $this->assertTrue(strpos((string) $result[0], $text) !== FALSE, 'Ensure the broken handler text was found.'); $original_configuration = [ diff --git a/core/profiles/minimal/config/install/block.block.stark_page_title.yml b/core/profiles/minimal/config/install/block.block.stark_page_title.yml new file mode 100644 index 0000000..6222884 --- /dev/null +++ b/core/profiles/minimal/config/install/block.block.stark_page_title.yml @@ -0,0 +1,18 @@ +id: stark_page_title +theme: stark +weight: -30 +status: true +langcode: en +region: content +plugin: page_title_block +settings: + id: page_title_block + label: Page title + provider: core + label_display: '0' + cache: + max_age: -1 +dependencies: + theme: + - stark +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.bartik_page_title.yml b/core/profiles/standard/config/install/block.block.bartik_page_title.yml new file mode 100644 index 0000000..f23677d --- /dev/null +++ b/core/profiles/standard/config/install/block.block.bartik_page_title.yml @@ -0,0 +1,18 @@ +id: bartik_page_title +theme: bartik +weight: -50 +status: true +langcode: en +region: content +plugin: page_title_block +settings: + id: page_title_block + label: Page title + provider: core + label_display: '0' + cache: + max_age: -1 +dependencies: + theme: + - bartik +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.classy_page_title.yml b/core/profiles/standard/config/install/block.block.classy_page_title.yml new file mode 100644 index 0000000..5674a48 --- /dev/null +++ b/core/profiles/standard/config/install/block.block.classy_page_title.yml @@ -0,0 +1,18 @@ +id: classy_page_title +theme: classy +weight: -50 +status: true +langcode: en +region: content +plugin: page_title_block +settings: + id: page_title_block + label: Page title + provider: core + label_display: '0' + cache: + max_age: -1 +dependencies: + theme: + - classy +visibility: { } diff --git a/core/profiles/standard/config/install/block.block.seven_page_title.yml b/core/profiles/standard/config/install/block.block.seven_page_title.yml new file mode 100644 index 0000000..b03f162 --- /dev/null +++ b/core/profiles/standard/config/install/block.block.seven_page_title.yml @@ -0,0 +1,18 @@ +id: page_title +theme: seven +weight: -30 +status: true +langcode: en +region: header +plugin: page_title_block +settings: + id: page_title_block + label: Page Title + provider: core + label_display: '0' + cache: + max_age: -1 +dependencies: + theme: + - seven +visibility: { } diff --git a/core/themes/bartik/bartik.theme b/core/themes/bartik/bartik.theme index 556342f..03dc8b4 100644 --- a/core/themes/bartik/bartik.theme +++ b/core/themes/bartik/bartik.theme @@ -39,7 +39,7 @@ function bartik_preprocess_html(&$variables) { /** * Implements hook_preprocess_HOOK() for page templates. */ -function bartik_preprocess_page(&$variables) { +function bartik_preprocess_page_title(&$variables) { // Since the title and the shortcut link are both block level elements, // positioning them next to each other is much simpler with a wrapper div. if (!empty($variables['title_suffix']['add_or_remove_shortcut']) && $variables['title']) { diff --git a/core/themes/bartik/templates/maintenance-page.html.twig b/core/themes/bartik/templates/maintenance-page.html.twig index 3cd787b..f071245 100644 --- a/core/themes/bartik/templates/maintenance-page.html.twig +++ b/core/themes/bartik/templates/maintenance-page.html.twig @@ -35,9 +35,6 @@
- {% if title %} -

{{ title }}

- {% endif %} {{ page.content }} {{ page.highlighted }}
diff --git a/core/themes/bartik/templates/page-title.html.twig b/core/themes/bartik/templates/page-title.html.twig new file mode 100644 index 0000000..e061cd2 --- /dev/null +++ b/core/themes/bartik/templates/page-title.html.twig @@ -0,0 +1,16 @@ +{% extends "@classy/content/page-title.html.twig" %} +{# +/** + * @file + * Bartik's theme implementation for a page title. + * + * Available variables: + * - title_attributes: HTML attributes for the page title element. + * - 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. + */ +#} +{% set title_attributes = title_attributes.addClass('title') %} diff --git a/core/themes/bartik/templates/page.html.twig b/core/themes/bartik/templates/page.html.twig index 8bcea09..7122143 100644 --- a/core/themes/bartik/templates/page.html.twig +++ b/core/themes/bartik/templates/page.html.twig @@ -27,11 +27,6 @@ * slogan has been disabled in theme settings. * Page content (in order of occurrence in the default page.html.twig): - * - 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. * - 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 @@ -90,13 +85,6 @@
- {{ title_prefix }} - {% if title %} -

- {{ title }} -

- {% endif %} - {{ title_suffix }} {{ page.content }}
diff --git a/core/themes/classy/templates/content/page-title.html.twig b/core/themes/classy/templates/content/page-title.html.twig new file mode 100644 index 0000000..adec853 --- /dev/null +++ b/core/themes/classy/templates/content/page-title.html.twig @@ -0,0 +1,21 @@ +{# +/** + * @file + * Theme override for page titles. + * + * Available variables: + * - title_attributes: HTML attributes for the page title element. + * - 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. + * + * @see template_preprocess_page_title() + */ +#} +{{ title_prefix }} +{% if title %} + {{ title }} +{% endif %} +{{ title_suffix }} diff --git a/core/themes/classy/templates/layout/page.html.twig b/core/themes/classy/templates/layout/page.html.twig index 0ac734b..f998a33 100644 --- a/core/themes/classy/templates/layout/page.html.twig +++ b/core/themes/classy/templates/layout/page.html.twig @@ -26,11 +26,6 @@ * slogan has been disabled in theme settings. * * Page content (in order of occurrence in the default page.html.twig): - * - 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. * - 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 @@ -72,12 +67,6 @@ {# link is in html.html.twig #}
- - {{ title_prefix }} - {% if title %} -

{{ title }}

- {% endif %} - {{ title_suffix }} {{ page.content }}
{# /.layout-content #} diff --git a/core/themes/seven/templates/page.html.twig b/core/themes/seven/templates/page.html.twig index 5698bfa..25597a1 100644 --- a/core/themes/seven/templates/page.html.twig +++ b/core/themes/seven/templates/page.html.twig @@ -27,11 +27,6 @@ * slogan has been disabled in theme settings. * * Page content (in order of occurrence in the default page.html.twig): - * - 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. * - 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,11 +47,6 @@ #}
- {{ title_prefix }} - {% if title %} -

{{ title }}

- {% endif %} - {{ title_suffix }} {{ page.header }}