diff --git a/core/modules/search/src/Controller/SearchController.php b/core/modules/search/src/Controller/SearchController.php index 0bb918f663b..b3b11226260 100644 --- a/core/modules/search/src/Controller/SearchController.php +++ b/core/modules/search/src/Controller/SearchController.php @@ -79,6 +79,7 @@ class SearchController extends ControllerBase { $plugin->setSearch($keys, $request->query->all(), $request->attributes->all()); } + $build['#title'] = $plugin->suggestedTitle(); $build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search'); // Build search results, if keywords or other search parameters are in the diff --git a/core/modules/search/src/Plugin/SearchInterface.php b/core/modules/search/src/Plugin/SearchInterface.php index 3c5f76d4cad..3d894ed421c 100644 --- a/core/modules/search/src/Plugin/SearchInterface.php +++ b/core/modules/search/src/Plugin/SearchInterface.php @@ -82,6 +82,14 @@ interface SearchInterface extends PluginInspectionInterface { */ public function buildResults(); + /** + * Provides a suggested title for a page of search results. + * + * @return string + * The translated suggested page title. + */ + public function suggestedTitle(); + /** * Alters the search form when being built for a given plugin. * diff --git a/core/modules/search/src/Plugin/SearchPluginBase.php b/core/modules/search/src/Plugin/SearchPluginBase.php index 75d030f4550..161dd716fe9 100644 --- a/core/modules/search/src/Plugin/SearchPluginBase.php +++ b/core/modules/search/src/Plugin/SearchPluginBase.php @@ -10,6 +10,7 @@ namespace Drupal\search\Plugin; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Plugin\PluginBase; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; +use Drupal\Component\Utility\Unicode; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -109,6 +110,19 @@ abstract class SearchPluginBase extends PluginBase implements ContainerFactoryPl // Empty default implementation. } + /** + * {@inheritdoc} + */ + public function suggestedTitle() { + // If the user entered a search string, truncate it and append it to the + // title. + if (!empty($this->keywords)) { + return $this->t('Search for @keywords', array('@keywords' => Unicode::truncate($this->keywords, 60, TRUE, TRUE))); + } + // Use the default 'Search' title. + return $this->t('Search'); + } + /* * {@inheritdoc} */ diff --git a/core/modules/search/src/Tests/SearchCommentTest.php b/core/modules/search/src/Tests/SearchCommentTest.php index 70d8c851026..9fb39384ac1 100644 --- a/core/modules/search/src/Tests/SearchCommentTest.php +++ b/core/modules/search/src/Tests/SearchCommentTest.php @@ -132,7 +132,7 @@ class SearchCommentTest extends SearchTestBase { // Search for $title. $this->drupalPostForm('search/node', $edit, t('Search')); - $this->assertNoText($comment_body, 'Comment body text not found in search results.'); + $this->assertText(t('Your search yielded no results.')); } /** @@ -226,8 +226,8 @@ class SearchCommentTest extends SearchTestBase { $expected_comment_result = $this->assertText($this->comment_subject); } else { - $expected_node_result = $this->assertNoText($this->node->label()); - $expected_comment_result = $this->assertNoText($this->comment_subject); + $expected_node_result = $this->assertText(t('Your search yielded no results.')); + $expected_comment_result = $this->assertText(t('Your search yielded no results.')); } $this->assertTrue($expected_node_result && $expected_comment_result, $message); } diff --git a/core/modules/search/src/Tests/SearchPageTextTest.php b/core/modules/search/src/Tests/SearchPageTextTest.php index b7729774ce2..ede9e4caaec 100644 --- a/core/modules/search/src/Tests/SearchPageTextTest.php +++ b/core/modules/search/src/Tests/SearchPageTextTest.php @@ -7,6 +7,8 @@ namespace Drupal\search\Tests; +use Drupal\Component\Utility\Unicode; + /** * Tests the bike shed text on no results page, and text on the search page. * @@ -30,23 +32,38 @@ class SearchPageTextTest extends SearchTestBase { $this->drupalGet('search/node'); $this->assertText(t('Enter your keywords')); $this->assertText(t('Search')); - $title = t('Search') . ' | Drupal'; - $this->assertTitle($title, 'Search page title is correct'); + $this->assertTitle(t('Search') . ' | Drupal', 'Search page title is correct'); $edit = array(); - $edit['keys'] = 'bike shed ' . $this->randomMachineName(); + $search_terms = 'bike shed ' . $this->randomMachineName(); + $edit['keys'] = $search_terms; $this->drupalPostForm('search/node', $edit, t('Search')); $this->assertText(t('Consider loosening your query with OR. bike OR shed will often show more results than bike shed.'), 'Help text is displayed when search returns no results.'); $this->assertText(t('Search')); - $this->assertTitle($title, 'Search page title is correct'); + $title_source = 'Search for @keywords | Drupal'; + $this->assertTitle(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE))), 'Search page title is correct'); $this->assertNoText('Node', 'Erroneous tab and breadcrumb text is not present'); $this->assertNoText(t('Node'), 'Erroneous translated tab and breadcrumb text is not present'); $this->assertText(t('Content'), 'Tab and breadcrumb text is present'); + // Search for a longer text, and see that it is in the title, truncated. + $edit = array(); + $search_terms = 'Every word is like an unnecessary stain on silence and nothingness.'; + $edit['keys'] = $search_terms; + $this->drupalPostForm('search/node', $edit, t('Search')); + $this->assertTitle(t($title_source, array('@keywords' => 'Every word is like an unnecessary stain on silence and…')), 'Search page title is correct'); + + // Search for a string with a lot of special characters. + $search_terms = 'Hear nothing > "see nothing" `feel' . " '1982."; + $edit['keys'] = $search_terms; + $this->drupalPostForm('search/node', $edit, t('Search')); + $actual_title = (string) current($this->xpath('//title')); + $this->assertEqual($actual_title, decode_entities(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)))), 'Search page title is correct'); + $edit['keys'] = $this->searching_user->getUsername(); $this->drupalPostForm('search/user', $edit, t('Search')); $this->assertText(t('Search')); - $this->assertTitle($title, 'Search page title is correct'); + $this->assertTitle(t($title_source, array('@keywords' => Unicode::truncate($this->searching_user->getUsername(), 60, TRUE, TRUE)))); // Test that search keywords containing slashes are correctly loaded // from the GET params and displayed in the search form. diff --git a/core/modules/user/src/Tests/UserSearchTest.php b/core/modules/user/src/Tests/UserSearchTest.php index 8d0c0c69d98..6f8af13cb37 100644 --- a/core/modules/user/src/Tests/UserSearchTest.php +++ b/core/modules/user/src/Tests/UserSearchTest.php @@ -32,7 +32,7 @@ class UserSearchTest extends WebTestBase { $keys = $user1->getEmail(); $edit = array('keys' => $keys); $this->drupalPostForm('search/user', $edit, t('Search')); - $this->assertNoText($keys, 'Search by email did not work for non-admin user'); + $this->assertText(t('Your search yielded no results.'), 'Search by email did not work for non-admin user'); $this->assertText('no results', 'Search by email gave no-match message'); // Verify that a non-matching query gives an appropriate message. @@ -105,7 +105,7 @@ class UserSearchTest extends WebTestBase { $this->drupalLogin($user1); $edit = array('keys' => $blocked_user->getUsername()); $this->drupalPostForm('search/user', $edit, t('Search')); - $this->assertNoText($blocked_user->getUsername(), 'Blocked users are hidden from the user search results.'); + $this->assertText(t('Your search yielded no results.'), 'Blocked users are hidden from the user search results.'); // Create a user without search permission, and one without user page view // permission. Verify that neither one can access the user search page.