Update to Drupal 8.0.0-beta15. For more information, see: https://www.drupal.org/node/2563023
This commit is contained in:
parent
2720a9ec4b
commit
f3791f1da3
1898 changed files with 54300 additions and 11481 deletions
|
@ -0,0 +1,24 @@
|
|||
id: d7_search_settings
|
||||
label: Drupal 7 search configuration
|
||||
migration_tags:
|
||||
- Drupal 7
|
||||
source:
|
||||
plugin: variable
|
||||
constants:
|
||||
status: true
|
||||
variables:
|
||||
- minimum_word_size
|
||||
- overlap_cjk
|
||||
- search_cron_limit
|
||||
- search_tag_weights
|
||||
- search_and_or_limit
|
||||
process:
|
||||
'index/minimum_word_size': minimum_word_size
|
||||
'index/overlap_cjk': overlap_cjk
|
||||
'index/cron_limit': search_cron_limit
|
||||
'index/tag_weights': search_tag_weights
|
||||
and_or_limit: search_and_or_limit
|
||||
logging: 'constants/status'
|
||||
destination:
|
||||
plugin: config
|
||||
config_name: search.settings
|
|
@ -5,7 +5,6 @@
|
|||
* Enables site-wide keyword searching.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Cache\Cache;
|
||||
|
@ -618,7 +617,8 @@ function search_mark_for_reindex($type = NULL, $sid = NULL, $langcode = NULL) {
|
|||
/**
|
||||
* Returns snippets from a piece of text, with search keywords highlighted.
|
||||
*
|
||||
* Used for formatting search results.
|
||||
* Used for formatting search results. All HTML tags will be stripped from
|
||||
* $text.
|
||||
*
|
||||
* @param string $keys
|
||||
* A string containing a search query.
|
||||
|
@ -627,8 +627,8 @@ function search_mark_for_reindex($type = NULL, $sid = NULL, $langcode = NULL) {
|
|||
* @param string|null $langcode
|
||||
* Language code for the language of $text, if known.
|
||||
*
|
||||
* @return string
|
||||
* A string containing HTML for the excerpt.
|
||||
* @return array
|
||||
* A render array containing HTML for the excerpt.
|
||||
*/
|
||||
function search_excerpt($keys, $text, $langcode = NULL) {
|
||||
// We highlight around non-indexable or CJK characters.
|
||||
|
@ -721,7 +721,9 @@ function search_excerpt($keys, $text, $langcode = NULL) {
|
|||
// We didn't find any keyword matches, so just return the first part of the
|
||||
// text. We also need to re-encode any HTML special characters that we
|
||||
// entity-decoded above.
|
||||
return SafeMarkup::checkPlain(Unicode::truncate($text, 256, TRUE, TRUE));
|
||||
return [
|
||||
'#plain_text' => Unicode::truncate($text, 256, TRUE, TRUE),
|
||||
];
|
||||
}
|
||||
|
||||
// Sort the text ranges by starting position.
|
||||
|
@ -762,12 +764,15 @@ function search_excerpt($keys, $text, $langcode = NULL) {
|
|||
// translated. Let translators have the … separator text as one chunk.
|
||||
$ellipses = explode('!excerpt', t('… !excerpt … !excerpt …'));
|
||||
$text = (isset($new_ranges[0]) ? '' : $ellipses[0]) . implode($ellipses[1], $out) . (($max_end < strlen($text) - 1) ? $ellipses[2] : '');
|
||||
$text = SafeMarkup::checkPlain($text);
|
||||
$text = Html::escape($text);
|
||||
|
||||
// Highlight keywords. Must be done at once to prevent conflicts ('strong'
|
||||
// and '<strong>').
|
||||
$text = trim(preg_replace('/' . $boundary . '(?:' . implode('|', $keys) . ')' . $boundary . '/iu', '<strong>\0</strong>', ' ' . $text . ' '));
|
||||
return SafeMarkup::xssFilter($text, ['strong']);
|
||||
return [
|
||||
'#markup' => $text,
|
||||
'#allowed_tags' => ['strong']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* User page callbacks for the Search module.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\UrlHelper;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
|
@ -35,8 +35,8 @@ function template_preprocess_search_result(&$variables) {
|
|||
$language_interface = \Drupal::languageManager()->getCurrentLanguage();
|
||||
|
||||
$result = $variables['result'];
|
||||
$variables['url'] = check_url($result['link']);
|
||||
$variables['title'] = SafeMarkup::checkPlain($result['title']);
|
||||
$variables['url'] = UrlHelper::stripDangerousProtocols($result['link']);
|
||||
$variables['title'] = $result['title'];
|
||||
if (isset($result['language']) && $result['language'] != $language_interface->getId() && $result['language'] != LanguageInterface::LANGCODE_NOT_SPECIFIED) {
|
||||
$variables['title_attributes']['lang'] = $result['language'];
|
||||
$variables['content_attributes']['lang'] = $result['language'];
|
||||
|
@ -44,7 +44,7 @@ function template_preprocess_search_result(&$variables) {
|
|||
|
||||
$info = array();
|
||||
if (!empty($result['plugin_id'])) {
|
||||
$info['plugin_id'] = SafeMarkup::checkPlain($result['plugin_id']);
|
||||
$info['plugin_id'] = $result['plugin_id'];
|
||||
}
|
||||
if (!empty($result['user'])) {
|
||||
$info['user'] = $result['user'];
|
||||
|
|
|
@ -93,10 +93,11 @@ class Search extends ArgumentPluginBase {
|
|||
$join = Views::pluginManager('join')->createInstance('standard', $definition);
|
||||
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
||||
|
||||
// Add the search score field to the query.
|
||||
$this->search_score = $this->query->addField('', "$search_index.score * $search_total.count", 'score', array('function' => 'sum'));
|
||||
|
||||
// Add the conditions set up by the search query to the views query.
|
||||
$search_condition->condition("$search_index.type", $this->searchType);
|
||||
|
||||
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||
$conditions = $this->searchQuery->conditions();
|
||||
$condition_conditions =& $conditions->conditions();
|
||||
|
@ -110,6 +111,16 @@ class Search extends ArgumentPluginBase {
|
|||
$search_conditions =& $search_condition->conditions();
|
||||
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
||||
|
||||
// Add the keyword conditions, as is done in
|
||||
// SearchQuery::prepareAndNormalize(), but simplified because we are
|
||||
// only concerned with relevance ranking so we do not need to normalize.
|
||||
$or = db_or();
|
||||
foreach ($words as $word) {
|
||||
$or->condition("$search_index.word", $word);
|
||||
}
|
||||
$search_condition->condition($or);
|
||||
|
||||
// Add the GROUP BY and HAVING expressions to the query.
|
||||
$this->query->addWhere(0, $search_condition);
|
||||
$this->query->addGroupBy("$search_index.sid");
|
||||
$matches = $this->searchQuery->matches();
|
||||
|
|
|
@ -166,11 +166,12 @@ class Search extends FilterPluginBase {
|
|||
'left_field' => 'word',
|
||||
);
|
||||
$join = Views::pluginManager('join')->createInstance('standard', $definition);
|
||||
|
||||
$search_total = $this->query->addRelationship('search_total', $join, $search_index);
|
||||
|
||||
// Add the search score field to the query.
|
||||
$this->search_score = $this->query->addField('', "$search_index.score * $search_total.count", 'score', array('function' => 'sum'));
|
||||
|
||||
// Add the conditions set up by the search query to the views query.
|
||||
$search_condition->condition("$search_index.type", $this->searchType);
|
||||
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||
$conditions = $this->searchQuery->conditions();
|
||||
|
@ -185,7 +186,18 @@ class Search extends FilterPluginBase {
|
|||
$search_conditions =& $search_condition->conditions();
|
||||
$search_conditions = array_merge($search_conditions, $condition_conditions);
|
||||
|
||||
// Add the keyword conditions, as is done in
|
||||
// SearchQuery::prepareAndNormalize(), but simplified because we are
|
||||
// only concerned with relevance ranking so we do not need to normalize.
|
||||
$or = db_or();
|
||||
foreach ($words as $word) {
|
||||
$or->condition("$search_index.word", $word);
|
||||
}
|
||||
$search_condition->condition($or);
|
||||
|
||||
$this->query->addWhere($this->options['group'], $search_condition);
|
||||
|
||||
// Add the GROUP BY and HAVING expressions to the query.
|
||||
$this->query->addGroupBy("$search_index.sid");
|
||||
$matches = $this->searchQuery->matches();
|
||||
$placeholder = $this->placeholder();
|
||||
|
|
|
@ -121,7 +121,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
*/
|
||||
public function buildRow(EntityInterface $entity) {
|
||||
/** @var $entity \Drupal\search\SearchPageInterface */
|
||||
$row['label'] = $this->getLabel($entity);
|
||||
$row['label'] = $entity->label();
|
||||
$row['url']['#markup'] = 'search/' . $entity->getPath();
|
||||
// If the search page is active, link to it.
|
||||
if ($entity->status()) {
|
||||
|
|
|
@ -14,7 +14,7 @@ use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
|||
/**
|
||||
* Upgrade search rank settings to search.page.*.yml.
|
||||
*
|
||||
* @group search
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateSearchPageTest extends MigrateDrupal6TestBase {
|
||||
|
||||
|
@ -30,7 +30,6 @@ class MigrateSearchPageTest extends MigrateDrupal6TestBase {
|
|||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->loadDumps(['Variable.php']);
|
||||
$this->executeMigration('d6_search_page');
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\search\Tests\Migrate\d6\MigrateSearchSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests\Migrate\d6;
|
||||
|
||||
use Drupal\config\Tests\SchemaCheckTestTrait;
|
||||
use Drupal\migrate_drupal\Tests\d6\MigrateDrupal6TestBase;
|
||||
|
||||
/**
|
||||
* Upgrade variables to search.settings.yml.
|
||||
*
|
||||
* @group migrate_drupal_6
|
||||
*/
|
||||
class MigrateSearchSettingsTest extends MigrateDrupal6TestBase {
|
||||
|
||||
use SchemaCheckTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('search');
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->executeMigration('d6_search_settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration of search variables to search.settings.yml.
|
||||
*/
|
||||
public function testSearchSettings() {
|
||||
$config = $this->config('search.settings');
|
||||
$this->assertIdentical(3, $config->get('index.minimum_word_size'));
|
||||
$this->assertIdentical(TRUE, $config->get('index.overlap_cjk'));
|
||||
$this->assertIdentical(100, $config->get('index.cron_limit'));
|
||||
$this->assertIdentical(TRUE, $config->get('logging'));
|
||||
$this->assertConfigSchema(\Drupal::service('config.typed'), 'search.settings', $config->get());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\search\Tests\Migrate\d7\MigrateSearchSettingsTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\search\Tests\Migrate\d7;
|
||||
|
||||
use Drupal\migrate_drupal\Tests\d7\MigrateDrupal7TestBase;
|
||||
|
||||
/**
|
||||
* Tests migration of Search variables to configuration.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class MigrateSearchSettingsTest extends MigrateDrupal7TestBase {
|
||||
|
||||
public static $modules = ['search'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->executeMigration('d7_search_settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the migration of Search's variables to configuration.
|
||||
*/
|
||||
public function testSearchSettings() {
|
||||
$config = $this->config('search.settings');
|
||||
$this->assertIdentical(4, $config->get('index.minimum_word_size'));
|
||||
$this->assertTrue($config->get('index.overlap_cjk'));
|
||||
$this->assertIdentical(100, $config->get('index.cron_limit'));
|
||||
$this->assertIdentical(7, $config->get('and_or_limit'));
|
||||
$this->assertIdentical(25, $config->get('index.tag_weights.h1'));
|
||||
$this->assertIdentical(18, $config->get('index.tag_weights.h2'));
|
||||
$this->assertIdentical(15, $config->get('index.tag_weights.h3'));
|
||||
$this->assertIdentical(12, $config->get('index.tag_weights.h4'));
|
||||
$this->assertIdentical(9, $config->get('index.tag_weights.h5'));
|
||||
$this->assertIdentical(6, $config->get('index.tag_weights.h6'));
|
||||
$this->assertIdentical(3, $config->get('index.tag_weights.u'));
|
||||
$this->assertIdentical(3, $config->get('index.tag_weights.b'));
|
||||
$this->assertIdentical(3, $config->get('index.tag_weights.i'));
|
||||
$this->assertIdentical(3, $config->get('index.tag_weights.strong'));
|
||||
$this->assertIdentical(3, $config->get('index.tag_weights.em'));
|
||||
$this->assertIdentical(10, $config->get('index.tag_weights.a'));
|
||||
$this->assertTrue($config->get('logging'));
|
||||
}
|
||||
|
||||
}
|
|
@ -126,6 +126,23 @@ class SearchCommentTest extends SearchTestBase {
|
|||
$edit_comment['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() .'/comment', $edit_comment, t('Save'));
|
||||
|
||||
// Post a comment with an evil script tag in the comment subject and a
|
||||
// script tag nearby a keyword in the comment body. Use the 'FULL HTML' text
|
||||
// format so the script tag stored.
|
||||
$edit_comment2 = array();
|
||||
$edit_comment2['subject[0][value]'] = "<script>alert('subjectkeyword');</script>";
|
||||
$edit_comment2['comment_body[0][value]'] = "nearbykeyword<script>alert('somethinggeneric');</script>";
|
||||
$edit_comment2['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment2, t('Save'));
|
||||
|
||||
// Post a comment with a keyword inside an evil script tag in the comment
|
||||
// body. Use the 'FULL HTML' text format so the script tag is stored.
|
||||
$edit_comment3 = array();
|
||||
$edit_comment3['subject[0][value]'] = 'asubject';
|
||||
$edit_comment3['comment_body[0][value]'] = "<script>alert('insidekeyword');</script>";
|
||||
$edit_comment3['comment_body[0][format]'] = $full_html_format_id;
|
||||
$this->drupalPostForm('comment/reply/node/' . $node->id() . '/comment', $edit_comment3, t('Save'));
|
||||
|
||||
// Invoke search index update.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
@ -152,6 +169,39 @@ class SearchCommentTest extends SearchTestBase {
|
|||
$this->assertNoRaw(t('n/a'), 'HTML in comment body is not hidden.');
|
||||
$this->assertNoEscaped($edit_comment['comment_body[0][value]'], 'HTML in comment body is not escaped.');
|
||||
|
||||
// Search for the evil script comment subject.
|
||||
$edit = array(
|
||||
'keys' => 'subjectkeyword',
|
||||
);
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// Verify the evil comment subject is escaped in search results.
|
||||
$this->assertRaw('<script>alert('<strong>subjectkeyword</strong>');');
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Search for the keyword near the evil script tag in the comment body.
|
||||
$edit = [
|
||||
'keys' => 'nearbykeyword',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// Verify that nearby script tag in the evil comment body is stripped from
|
||||
// search results.
|
||||
$this->assertRaw('<strong>nearbykeyword</strong>');
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Search for contents inside the evil script tag in the comment body.
|
||||
$edit = [
|
||||
'keys' => 'insidekeyword',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
// @todo Verify the actual search results.
|
||||
// https://www.drupal.org/node/2551135
|
||||
|
||||
// Verify there is no script tag in search results.
|
||||
$this->assertNoRaw('<script>');
|
||||
|
||||
// Hide comments.
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$node->set('comment', CommentItemInterface::HIDDEN);
|
||||
|
|
|
@ -58,6 +58,7 @@ class SearchConfigSettingsFormTest extends SearchTestBase {
|
|||
|
||||
// Enable the search block.
|
||||
$this->drupalPlaceBlock('search_form_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests the search_excerpt() function.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchExcerptTest extends WebTestBase {
|
||||
class SearchExcerptTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
|
@ -38,39 +38,39 @@ class SearchExcerptTest extends WebTestBase {
|
|||
// Note: The search_excerpt() function adds some extra spaces -- not
|
||||
// important for HTML formatting. Remove these for comparison.
|
||||
$expected = 'The quick brown fox & jumps over the lazy dog';
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('nothing', $text));
|
||||
$this->assertEqual(preg_replace('| +|', ' ', $result), $expected, 'Entire string is returned when keyword is not found in short string');
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('nothing', $text));
|
||||
$this->assertEqual(preg_replace('| +|', ' ', $result), $expected, 'Entire string, stripped of HTML tags, is returned when keyword is not found in short string');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('fox', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('fox', $text));
|
||||
$this->assertEqual($result, 'The quick brown <strong>fox</strong> & jumps over the lazy dog', 'Found keyword is highlighted');
|
||||
|
||||
$expected = '<strong>The</strong> quick brown fox & jumps over <strong>the</strong> lazy dog';
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('The', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('The', $text));
|
||||
$this->assertEqual(preg_replace('| +|', ' ', $result), $expected, 'Keyword is highlighted at beginning of short string');
|
||||
|
||||
$expected = 'The quick brown fox & jumps over the lazy <strong>dog</strong>';
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('dog', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('dog', $text));
|
||||
$this->assertEqual(preg_replace('| +|', ' ', $result), $expected, 'Keyword is highlighted at end of short string');
|
||||
|
||||
$longtext = str_repeat(str_replace('brown', 'silver', $text) . ' ', 10) . $text . str_repeat(' ' . str_replace('brown', 'pink', $text), 10);
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('brown', $longtext));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('brown', $longtext));
|
||||
$expected = '… silver fox & jumps over the lazy dog The quick <strong>brown</strong> fox & jumps over the lazy dog The quick …';
|
||||
$this->assertEqual($result, $expected, 'Snippet around keyword in long text is correctly capped');
|
||||
|
||||
$longtext = str_repeat($text . ' ', 10);
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('nothing', $longtext));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('nothing', $longtext));
|
||||
$expected = 'The quick brown fox & jumps over the lazy dog';
|
||||
$this->assertTrue(strpos($result, $expected) === 0, 'When keyword is not found in long string, return value starts as expected');
|
||||
|
||||
$entities = str_repeat('készítése ', 20);
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('nothing', $entities));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('nothing', $entities));
|
||||
$this->assertFalse(strpos($result, '&'), 'Entities are not present in excerpt');
|
||||
$this->assertTrue(strpos($result, 'í') > 0, 'Entities are converted in excerpt');
|
||||
|
||||
// The node body that will produce this rendered $text is:
|
||||
// 123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘
|
||||
$text = "<div class=\"field field-name-body field-type-text-with-summary field-label-hidden\"><div class=\"field-items\"><div class=\"field-item even\" property=\"content:encoded\"><p>123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘</p>\n</div></div></div> ";
|
||||
$result = search_excerpt('HTMLTest', $text);
|
||||
$text = "<div class=\"field field--name-body field--type-text-with-summary field--label-hidden\"><div class=\"field__items\"><div class=\"field__item even\" property=\"content:encoded\"><p>123456789 HTMLTest +123456789+‘ +‘ +‘ +‘ +12345678 +‘ +‘ +‘ ‘</p>\n</div></div></div> ";
|
||||
$result = $this->doSearchExcerpt('HTMLTest', $text);
|
||||
$this->assertFalse(empty($result), 'Rendered Multi-byte HTML encodings are not corrupted in search excerpts');
|
||||
}
|
||||
|
||||
|
@ -89,37 +89,37 @@ class SearchExcerptTest extends WebTestBase {
|
|||
$text = $lorem1 . ' Number: 123456.7890 Hyphenated: one-two abc,def ' . $lorem2;
|
||||
// Note: The search_excerpt() function adds some extra spaces -- not
|
||||
// important for HTML formatting. Remove these for comparison.
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('123456.7890', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('123456.7890', $text));
|
||||
$this->assertTrue(strpos($result, 'Number: <strong>123456.7890</strong>') !== FALSE, 'Numeric keyword is highlighted with exact match');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('1234567890', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('1234567890', $text));
|
||||
$this->assertTrue(strpos($result, 'Number: <strong>123456.7890</strong>') !== FALSE, 'Numeric keyword is highlighted with simplified match');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('Number 1234567890', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('Number 1234567890', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>Number</strong>: <strong>123456.7890</strong>') !== FALSE, 'Punctuated and numeric keyword is highlighted with simplified match');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('"Number 1234567890"', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('"Number 1234567890"', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>Number: 123456.7890</strong>') !== FALSE, 'Phrase with punctuated and numeric keyword is highlighted with simplified match');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('"Hyphenated onetwo"', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('"Hyphenated onetwo"', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>Hyphenated: one-two</strong>') !== FALSE, 'Phrase with punctuated and hyphenated keyword is highlighted with simplified match');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('"abc def"', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('"abc def"', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>abc,def</strong>') !== FALSE, 'Phrase with keyword simplified into two separate words is highlighted with simplified match');
|
||||
|
||||
// Test phrases with characters which are being truncated.
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('"ipsum _"', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('"ipsum _"', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>ipsum</strong>') !== FALSE, 'Only valid part of the phrase is highlighted and invalid part containing "_" is ignored.');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('"ipsum 0000"', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('"ipsum 0000"', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>ipsum</strong>') !== FALSE, 'Only valid part of the phrase is highlighted and invalid part "0000" is ignored.');
|
||||
|
||||
// Test combination of the valid keyword and keyword containing only
|
||||
// characters which are being truncated during simplification.
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('ipsum _', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('ipsum _', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>ipsum</strong>') !== FALSE, 'Only valid keyword is highlighted and invalid keyword "_" is ignored.');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('ipsum 0000', $text));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('ipsum 0000', $text));
|
||||
$this->assertTrue(strpos($result, '<strong>ipsum</strong>') !== FALSE, 'Only valid keyword is highlighted and invalid keyword "0000" is ignored.');
|
||||
|
||||
// Test using the hook_search_preprocess() from the test module.
|
||||
|
@ -127,37 +127,55 @@ class SearchExcerptTest extends WebTestBase {
|
|||
// So, if we search for "find" or "finds" or "finding", we should
|
||||
// highlight "finding".
|
||||
$text = "this tests finding a string";
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('finds', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('finds', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>finding</strong>') !== FALSE, 'Search excerpt works with preprocess hook, search for finds');
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('find', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('find', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>finding</strong>') !== FALSE, 'Search excerpt works with preprocess hook, search for find');
|
||||
|
||||
// Just to be sure, test with the replacement at the beginning and end.
|
||||
$text = "finding at the beginning";
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('finds', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('finds', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>finding</strong>') !== FALSE, 'Search excerpt works with preprocess hook, text at start');
|
||||
|
||||
$text = "at the end finding";
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('finds', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('finds', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>finding</strong>') !== FALSE, 'Search excerpt works with preprocess hook, text at end');
|
||||
|
||||
// Testing with a one-to-many replacement: the test module replaces DIC
|
||||
// with Dependency Injection Container.
|
||||
$text = "something about the DIC is happening";
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('Dependency', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('Dependency', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>DIC</strong>') !== FALSE, 'Search excerpt works with preprocess hook, acronym first word');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('Injection', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('Injection', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>DIC</strong>') !== FALSE, 'Search excerpt works with preprocess hook, acronym second word');
|
||||
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('Container', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('Container', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>DIC</strong>') !== FALSE, 'Search excerpt works with preprocess hook, acronym third word');
|
||||
|
||||
// Testing with a many-to-one replacement: the test module replaces
|
||||
// hypertext markup language with HTML.
|
||||
$text = "we always use hypertext markup language to describe things";
|
||||
$result = preg_replace('| +|', ' ', search_excerpt('html', $text, 'ex'));
|
||||
$result = preg_replace('| +|', ' ', $this->doSearchExcerpt('html', $text, 'ex'));
|
||||
$this->assertTrue(strpos($result, '<strong>hypertext markup language</strong>') !== FALSE, 'Search excerpt works with preprocess hook, acronym many to one');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls search_excerpt() and renders output.
|
||||
*
|
||||
* @param string $keys
|
||||
* A string containing a search query.
|
||||
* @param string $render_array
|
||||
* The text to extract fragments from.
|
||||
* @param string|null $langcode
|
||||
* Language code for the language of $text, if known.
|
||||
*
|
||||
* @return string
|
||||
* A string containing HTML for the excerpt.
|
||||
*/
|
||||
protected function doSearchExcerpt($keys, $render_array, $langcode = NULL) {
|
||||
$render_array = search_excerpt($keys, $render_array, $langcode);
|
||||
return \Drupal::service('renderer')->renderPlain($render_array);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Utility\Html;
|
||||
|
||||
/**
|
||||
* Verify the search without keywords set and extra conditions.
|
||||
|
@ -61,6 +61,6 @@ class SearchKeywordsConditionsTest extends SearchTestBase {
|
|||
$keys = 'moving drop ' . $this->randomMachineName();
|
||||
$this->drupalGet("search/dummy_path", array('query' => array('keys' => 'bike', 'search_conditions' => $keys)));
|
||||
$this->assertText("Dummy search snippet to display.");
|
||||
$this->assertRaw(SafeMarkup::checkPlain(print_r(array('keys' => 'bike', 'search_conditions' => $keys), TRUE)));
|
||||
$this->assertRaw(Html::escape(print_r(array('keys' => 'bike', 'search_conditions' => $keys), TRUE)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
// The search index can contain different types of content. Typically the type
|
||||
// is 'node'. Here we test with _test_ and _test2_ as the type.
|
||||
|
@ -20,7 +21,24 @@ const SEARCH_TYPE_JPN = '_test3_';
|
|||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchMatchTest extends SearchTestBase {
|
||||
class SearchMatchTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['search'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installSchema('search', ['search_index', 'search_dataset', 'search_total']);
|
||||
$this->installConfig(['search']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test search indexing.
|
||||
*/
|
||||
|
|
|
@ -23,11 +23,22 @@ class SearchPageTextTest extends SearchTestBase {
|
|||
*/
|
||||
protected $searchingUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$this->searchingUser = $this->drupalCreateUser(array('search content', 'access user profiles', 'use advanced search'));
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -69,8 +69,10 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
* The searched value.
|
||||
* @param string $replace
|
||||
* The value which replaces the search value.
|
||||
* @param \Drupal\Core\Database\Query\Condition $condition
|
||||
* The query condition in which the string is replaced.
|
||||
* @param array $condition
|
||||
* The query conditions array in which the string is replaced. This is an
|
||||
* item from a \Drupal\Core\Database\Query\Condition::conditions array,
|
||||
* which must have a 'field' element.
|
||||
*/
|
||||
function conditionReplaceString($search, $replace, &$condition) {
|
||||
if ($condition['field'] instanceof Condition) {
|
||||
|
|
|
@ -9,12 +9,10 @@
|
|||
* individual product (node) listed in the search results.
|
||||
*/
|
||||
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
|
||||
/**
|
||||
* Adds the test form to search results.
|
||||
*/
|
||||
function search_embedded_form_preprocess_search_result(&$variables) {
|
||||
$form = \Drupal::formBuilder()->getForm('Drupal\search_embedded_form\Form\SearchEmbeddedForm');
|
||||
$variables['snippet'] = ['#markup' => SafeMarkup::escape($variables['snippet']), $form];
|
||||
$variables['snippet'] = array_merge($variables['snippet'], $form);
|
||||
}
|
||||
|
|
Reference in a new issue