Update Composer, update everything
This commit is contained in:
parent
ea3e94409f
commit
dda5c284b6
19527 changed files with 1135420 additions and 351004 deletions
|
@ -5,6 +5,7 @@ namespace Drupal\search\Controller;
|
|||
use Drupal\Core\Cache\CacheableDependencyInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\search\Form\SearchPageForm;
|
||||
use Drupal\search\SearchPageInterface;
|
||||
use Drupal\search\SearchPageRepositoryInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
@ -84,7 +85,7 @@ class SearchController extends ControllerBase {
|
|||
}
|
||||
|
||||
$build['#title'] = $plugin->suggestedTitle();
|
||||
$build['search_form'] = $this->entityFormBuilder()->getForm($entity, 'search');
|
||||
$build['search_form'] = $this->formBuilder()->getForm(SearchPageForm::class, $entity);
|
||||
|
||||
// Build search results, if keywords or other search parameters are in the
|
||||
// GET parameters. Note that we need to try the search if 'keys' is in
|
||||
|
@ -103,7 +104,7 @@ class SearchController extends ControllerBase {
|
|||
else {
|
||||
// The search not being executable means that no keywords or other
|
||||
// conditions were entered.
|
||||
drupal_set_message($this->t('Please enter some keywords.'), 'error');
|
||||
$this->messenger()->addError($this->t('Please enter some keywords.'));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,8 +149,6 @@ class SearchController extends ControllerBase {
|
|||
/**
|
||||
* Creates a render array for the search help page.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\Request $request
|
||||
* The request object.
|
||||
* @param \Drupal\search\SearchPageInterface $entity
|
||||
* The search page entity.
|
||||
*
|
||||
|
@ -207,10 +206,10 @@ class SearchController extends ControllerBase {
|
|||
$search_page->$op()->save();
|
||||
|
||||
if ($op == 'enable') {
|
||||
drupal_set_message($this->t('The %label search page has been enabled.', ['%label' => $search_page->label()]));
|
||||
$this->messenger()->addStatus($this->t('The %label search page has been enabled.', ['%label' => $search_page->label()]));
|
||||
}
|
||||
elseif ($op == 'disable') {
|
||||
drupal_set_message($this->t('The %label search page has been disabled.', ['%label' => $search_page->label()]));
|
||||
$this->messenger()->addStatus($this->t('The %label search page has been disabled.', ['%label' => $search_page->label()]));
|
||||
}
|
||||
|
||||
$url = $search_page->urlInfo('collection');
|
||||
|
@ -230,7 +229,7 @@ class SearchController extends ControllerBase {
|
|||
// Set the default page to this search page.
|
||||
$this->searchPageRepository->setDefaultSearchPage($search_page);
|
||||
|
||||
drupal_set_message($this->t('The default search page is now %label. Be sure to check the ordering of your search pages.', ['%label' => $search_page->label()]));
|
||||
$this->messenger()->addStatus($this->t('The default search page is now %label. Be sure to check the ordering of your search pages.', ['%label' => $search_page->label()]));
|
||||
return $this->redirect('entity.search_page.collection');
|
||||
}
|
||||
|
||||
|
|
|
@ -16,13 +16,19 @@ use Drupal\search\SearchPageInterface;
|
|||
* @ConfigEntityType(
|
||||
* id = "search_page",
|
||||
* label = @Translation("Search page"),
|
||||
* label_collection = @Translation("Search pages"),
|
||||
* label_singular = @Translation("search page"),
|
||||
* label_plural = @Translation("search pages"),
|
||||
* label_count = @PluralTranslation(
|
||||
* singular = "@count search page",
|
||||
* plural = "@count search pages",
|
||||
* ),
|
||||
* handlers = {
|
||||
* "access" = "Drupal\search\SearchPageAccessControlHandler",
|
||||
* "list_builder" = "Drupal\search\SearchPageListBuilder",
|
||||
* "form" = {
|
||||
* "add" = "Drupal\search\Form\SearchPageAddForm",
|
||||
* "edit" = "Drupal\search\Form\SearchPageEditForm",
|
||||
* "search" = "Drupal\search\Form\SearchPageForm",
|
||||
* "delete" = "Drupal\Core\Entity\EntityDeleteForm"
|
||||
* }
|
||||
* },
|
||||
|
|
|
@ -8,6 +8,8 @@ use Drupal\Core\Url;
|
|||
|
||||
/**
|
||||
* Provides the search reindex confirmation form.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class ReindexConfirm extends ConfirmFormBase {
|
||||
|
||||
|
@ -63,7 +65,7 @@ class ReindexConfirm extends ConfirmFormBase {
|
|||
foreach ($search_page_repository->getIndexableSearchPages() as $entity) {
|
||||
$entity->getPlugin()->markForReindex();
|
||||
}
|
||||
drupal_set_message($this->t('All search indexes will be rebuilt.'));
|
||||
$this->messenger()->addStatus($this->t('All search indexes will be rebuilt.'));
|
||||
$form_state->setRedirectUrl($this->getCancelUrl());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
|
||||
/**
|
||||
* Builds the search form for the search block.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SearchBlockForm extends FormBase {
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for adding a search page.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SearchPageAddForm extends SearchPageFormBase {
|
||||
|
||||
|
@ -39,7 +41,7 @@ class SearchPageAddForm extends SearchPageFormBase {
|
|||
|
||||
parent::save($form, $form_state);
|
||||
|
||||
drupal_set_message($this->t('The %label search page has been added.', ['%label' => $this->entity->label()]));
|
||||
$this->messenger()->addStatus($this->t('The %label search page has been added.', ['%label' => $this->entity->label()]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ use Drupal\Core\Form\FormStateInterface;
|
|||
|
||||
/**
|
||||
* Provides a form for editing a search page.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SearchPageEditForm extends SearchPageFormBase {
|
||||
|
||||
|
@ -24,7 +26,7 @@ class SearchPageEditForm extends SearchPageFormBase {
|
|||
public function save(array $form, FormStateInterface $form_state) {
|
||||
parent::save($form, $form_state);
|
||||
|
||||
drupal_set_message($this->t('The %label search page has been updated.', ['%label' => $this->entity->label()]));
|
||||
$this->messenger()->addStatus($this->t('The %label search page has been updated.', ['%label' => $this->entity->label()]));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
|
||||
namespace Drupal\search\Form;
|
||||
|
||||
use Drupal\Core\Entity\EntityForm;
|
||||
use Drupal\Core\Form\FormBase;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\search\SearchPageInterface;
|
||||
|
||||
/**
|
||||
* Provides a search form for site wide search.
|
||||
|
@ -14,11 +15,13 @@ use Drupal\Core\Url;
|
|||
* submit, making sure to redirect with a GET parameter of 'keys' included, to
|
||||
* trigger the search being processed by the controller, and adding in any
|
||||
* additional query parameters they need to execute search.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class SearchPageForm extends EntityForm {
|
||||
class SearchPageForm extends FormBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* The search page entity.
|
||||
*
|
||||
* @var \Drupal\search\SearchPageInterface
|
||||
*/
|
||||
|
@ -34,7 +37,9 @@ class SearchPageForm extends EntityForm {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function form(array $form, FormStateInterface $form_state) {
|
||||
public function buildForm(array $form, FormStateInterface $form_state, SearchPageInterface $search_page = NULL) {
|
||||
$this->entity = $search_page;
|
||||
|
||||
$plugin = $this->entity->getPlugin();
|
||||
$form_state->set('search_page_id', $this->entity->id());
|
||||
|
||||
|
@ -72,16 +77,7 @@ class SearchPageForm extends EntityForm {
|
|||
|
||||
// Allow the plugin to add to or alter the search form.
|
||||
$plugin->searchFormAlter($form, $form_state);
|
||||
|
||||
return parent::form($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function actions(array $form, FormStateInterface $form_state) {
|
||||
// The submit button is added in the form directly.
|
||||
return [];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -23,7 +23,7 @@ abstract class ConfigurableSearchPluginBase extends SearchPluginBase implements
|
|||
public function __construct(array $configuration, $plugin_id, $plugin_definition) {
|
||||
parent::__construct($configuration, $plugin_id, $plugin_definition);
|
||||
|
||||
$this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $this->configuration);
|
||||
$this->setConfiguration($configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ abstract class ConfigurableSearchPluginBase extends SearchPluginBase implements
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function setConfiguration(array $configuration) {
|
||||
$this->configuration = $configuration;
|
||||
$this->configuration = NestedArray::mergeDeep($this->defaultConfiguration(), $configuration);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -110,7 +110,7 @@ interface SearchInterface extends PluginInspectionInterface {
|
|||
*
|
||||
* The core search module only invokes this method on active module plugins
|
||||
* when building a form for them in
|
||||
* \Drupal\search\Form\SearchPageForm::form(). A plugin implementing this
|
||||
* \Drupal\search\Form\SearchPageForm::buildForm(). A plugin implementing this
|
||||
* will also need to implement the buildSearchUrlQuery() method.
|
||||
*
|
||||
* @param array $form
|
||||
|
|
|
@ -146,16 +146,18 @@ abstract class SearchPluginBase extends PluginBase implements ContainerFactoryPl
|
|||
public function getHelp() {
|
||||
// This default search help is appropriate for plugins like NodeSearch
|
||||
// that use the SearchQuery class.
|
||||
$help = ['list' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => [
|
||||
$this->t('Search looks for exact, case-insensitive keywords; keywords shorter than a minimum length are ignored.'),
|
||||
$this->t('Use upper-case OR to get more results. Example: cat OR dog (content contains either "cat" or "dog").'),
|
||||
$this->t('You can use upper-case AND to require all words, but this is the same as the default behavior. Example: cat AND dog (same as cat dog, content must contain both "cat" and "dog").'),
|
||||
$this->t('Use quotes to search for a phrase. Example: "the cat eats mice".'),
|
||||
$this->t('You can precede keywords by - to exclude them; you must still have at least one "positive" keyword. Example: cat -dog (content must contain cat and cannot contain dog).'),
|
||||
$help = [
|
||||
'list' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => [
|
||||
$this->t('Search looks for exact, case-insensitive keywords; keywords shorter than a minimum length are ignored.'),
|
||||
$this->t('Use upper-case OR to get more results. Example: cat OR dog (content contains either "cat" or "dog").'),
|
||||
$this->t('You can use upper-case AND to require all words, but this is the same as the default behavior. Example: cat AND dog (same as cat dog, content must contain both "cat" and "dog").'),
|
||||
$this->t('Use quotes to search for a phrase. Example: "the cat eats mice".'),
|
||||
$this->t('You can precede keywords by - to exclude them; you must still have at least one "positive" keyword. Example: cat -dog (content must contain cat and cannot contain dog).'),
|
||||
],
|
||||
],
|
||||
]];
|
||||
];
|
||||
|
||||
return $help;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\search\Plugin\views\argument;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
use Drupal\views\ViewExecutable;
|
||||
|
@ -76,7 +77,7 @@ class Search extends ArgumentPluginBase {
|
|||
else {
|
||||
$search_index = $this->ensureMyTable();
|
||||
|
||||
$search_condition = db_and();
|
||||
$search_condition = new Condition('AND');
|
||||
|
||||
// Create a new join to relate the 'search_total' table to our current 'search_index' table.
|
||||
$definition = [
|
||||
|
@ -96,7 +97,7 @@ class Search extends ArgumentPluginBase {
|
|||
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||
$conditions = $this->searchQuery->conditions();
|
||||
$condition_conditions =& $conditions->conditions();
|
||||
foreach ($condition_conditions as $key => &$condition) {
|
||||
foreach ($condition_conditions as $key => &$condition) {
|
||||
// Make sure we just look at real conditions.
|
||||
if (is_numeric($key)) {
|
||||
// Replace the conditions with the table alias of views.
|
||||
|
@ -109,7 +110,7 @@ class Search extends ArgumentPluginBase {
|
|||
// 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();
|
||||
$or = new Condition('OR');
|
||||
foreach ($words as $word) {
|
||||
$or->condition("$search_index.word", $word);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Drupal\search\Plugin\views\filter;
|
||||
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\views\Plugin\views\filter\FilterPluginBase;
|
||||
use Drupal\views\Plugin\views\display\DisplayPluginBase;
|
||||
|
@ -33,6 +34,8 @@ class Search extends FilterPluginBase {
|
|||
|
||||
/**
|
||||
* TRUE if the search query has been parsed.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $parsed = FALSE;
|
||||
|
||||
|
@ -150,7 +153,7 @@ class Search extends FilterPluginBase {
|
|||
else {
|
||||
$search_index = $this->ensureMyTable();
|
||||
|
||||
$search_condition = db_and();
|
||||
$search_condition = new Condition('AND');
|
||||
|
||||
// Create a new join to relate the 'search_total' table to our current
|
||||
// 'search_index' table.
|
||||
|
@ -171,7 +174,7 @@ class Search extends FilterPluginBase {
|
|||
$search_dataset = $this->query->addTable('node_search_dataset');
|
||||
$conditions = $this->searchQuery->conditions();
|
||||
$condition_conditions =& $conditions->conditions();
|
||||
foreach ($condition_conditions as $key => &$condition) {
|
||||
foreach ($condition_conditions as $key => &$condition) {
|
||||
// Make sure we just look at real conditions.
|
||||
if (is_numeric($key)) {
|
||||
// Replace the conditions with the table alias of views.
|
||||
|
@ -184,7 +187,7 @@ class Search extends FilterPluginBase {
|
|||
// 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();
|
||||
$or = new Condition('OR');
|
||||
foreach ($words as $word) {
|
||||
$or->condition("$search_index.word", $word);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Form\ConfigFormBaseTrait;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Messenger\MessengerInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
|
@ -42,6 +43,13 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
*/
|
||||
protected $searchManager;
|
||||
|
||||
/**
|
||||
* The messenger.
|
||||
*
|
||||
* @var \Drupal\Core\Messenger\MessengerInterface
|
||||
*/
|
||||
protected $messenger;
|
||||
|
||||
/**
|
||||
* Constructs a new SearchPageListBuilder object.
|
||||
*
|
||||
|
@ -53,11 +61,14 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
* The search plugin manager.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The factory for configuration objects.
|
||||
* @param \Drupal\Core\Messenger\MessengerInterface $messenger
|
||||
* The messenger.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, SearchPluginManager $search_manager, ConfigFactoryInterface $config_factory) {
|
||||
public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, SearchPluginManager $search_manager, ConfigFactoryInterface $config_factory, MessengerInterface $messenger) {
|
||||
parent::__construct($entity_type, $storage);
|
||||
$this->configFactory = $config_factory;
|
||||
$this->searchManager = $search_manager;
|
||||
$this->messenger = $messenger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +79,8 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
$entity_type,
|
||||
$container->get('entity.manager')->getStorage($entity_type->id()),
|
||||
$container->get('plugin.manager.search'),
|
||||
$container->get('config.factory')
|
||||
$container->get('config.factory'),
|
||||
$container->get('messenger')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -145,7 +157,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
$status = $entity->getPlugin()->indexStatus();
|
||||
$row['progress']['#markup'] = $this->t('%num_indexed of %num_total indexed', [
|
||||
'%num_indexed' => $status['total'] - $status['remaining'],
|
||||
'%num_total' => $status['total']
|
||||
'%num_total' => $status['total'],
|
||||
]);
|
||||
}
|
||||
else {
|
||||
|
@ -215,7 +227,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
'#open' => TRUE,
|
||||
];
|
||||
$form['indexing_settings']['info'] = [
|
||||
'#markup' => $this->t("<p>Search pages that use an index may use the default index provided by the Search module, or they may use a different indexing mechanism. These settings are for the default index. <em>Changing these settings will cause the default search index to be rebuilt to reflect the new settings. Searching will continue to work, based on the existing index, but new content won't be indexed until all existing content has been re-indexed.</em></p><p><em>The default settings should be appropriate for the majority of sites.</em></p>")
|
||||
'#markup' => $this->t("<p>Search pages that use an index may use the default index provided by the Search module, or they may use a different indexing mechanism. These settings are for the default index. <em>Changing these settings will cause the default search index to be rebuilt to reflect the new settings. Searching will continue to work, based on the existing index, but new content won't be indexed until all existing content has been re-indexed.</em></p><p><em>The default settings should be appropriate for the majority of sites.</em></p>"),
|
||||
];
|
||||
$form['indexing_settings']['minimum_word_size'] = [
|
||||
'#type' => 'number',
|
||||
|
@ -229,7 +241,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
'#type' => 'checkbox',
|
||||
'#title' => $this->t('Simple CJK handling'),
|
||||
'#default_value' => $search_settings->get('index.overlap_cjk'),
|
||||
'#description' => $this->t('Whether to apply a simple Chinese/Japanese/Korean tokenizer based on overlapping sequences. Turn this off if you want to use an external preprocessor for this instead. Does not affect other languages.')
|
||||
'#description' => $this->t('Whether to apply a simple Chinese/Japanese/Korean tokenizer based on overlapping sequences. Turn this off if you want to use an external preprocessor for this instead. Does not affect other languages.'),
|
||||
];
|
||||
|
||||
// Indexing settings:
|
||||
|
@ -333,7 +345,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
$search_settings->set('index.overlap_cjk', $form_state->getValue('overlap_cjk'));
|
||||
// Specifically mark items in the default index for reindexing, since
|
||||
// these settings are used in the search_index() function.
|
||||
drupal_set_message($this->t('The default search index will be rebuilt.'));
|
||||
$this->messenger->addStatus($this->t('The default search index will be rebuilt.'));
|
||||
search_mark_for_reindex();
|
||||
}
|
||||
|
||||
|
@ -342,7 +354,7 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac
|
|||
->set('logging', $form_state->getValue('logging'))
|
||||
->save();
|
||||
|
||||
drupal_set_message($this->t('The configuration options have been saved.'));
|
||||
$this->messenger->addStatus($this->t('The configuration options have been saved.'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Drupal\search;
|
||||
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
use Drupal\Core\Database\Query\Condition;
|
||||
use Drupal\Core\Database\Query\SelectExtender;
|
||||
use Drupal\Core\Database\Query\SelectInterface;
|
||||
|
||||
|
@ -205,7 +205,7 @@ class SearchQuery extends SelectExtender {
|
|||
$this->addTag('search_' . $type);
|
||||
|
||||
// Initialize conditions and status.
|
||||
$this->conditions = db_and();
|
||||
$this->conditions = new Condition('AND');
|
||||
$this->status = 0;
|
||||
|
||||
return $this;
|
||||
|
@ -313,7 +313,7 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
$has_or = TRUE;
|
||||
$has_new_scores = FALSE;
|
||||
$queryor = db_or();
|
||||
$queryor = new Condition('OR');
|
||||
foreach ($key as $or) {
|
||||
list($num_new_scores) = $this->parseWord($or);
|
||||
$has_new_scores |= $num_new_scores;
|
||||
|
@ -363,7 +363,7 @@ class SearchQuery extends SelectExtender {
|
|||
$split = explode(' ', $word);
|
||||
foreach ($split as $s) {
|
||||
$num = is_numeric($s);
|
||||
if ($num || Unicode::strlen($s) >= \Drupal::config('search.settings')->get('index.minimum_word_size')) {
|
||||
if ($num || mb_strlen($s) >= \Drupal::config('search.settings')->get('index.minimum_word_size')) {
|
||||
if (!isset($this->words[$s])) {
|
||||
$this->words[$s] = $s;
|
||||
$num_new_scores++;
|
||||
|
@ -401,7 +401,7 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
|
||||
// Build the basic search query: match the entered keywords.
|
||||
$or = db_or();
|
||||
$or = new Condition('OR');
|
||||
foreach ($this->words as $word) {
|
||||
$or->condition('i.word', $word);
|
||||
}
|
||||
|
@ -570,10 +570,9 @@ class SearchQuery extends SelectExtender {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Add arguments for the keyword relevance normalization number.
|
||||
$normalization = 1.0 / $this->normalize;
|
||||
for ($i = 0; $i < $this->relevance_count; $i++ ) {
|
||||
for ($i = 0; $i < $this->relevance_count; $i++) {
|
||||
$this->scoresArguments[':normalization_' . $i] = $normalization;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Indexes content and tests the advanced search form.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchAdvancedSearchFormTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* A node to use for testing.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
// Create initial node.
|
||||
$this->node = $this->drupalCreateNode();
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests advanced search by node type.
|
||||
*/
|
||||
public function testNodeType() {
|
||||
// Verify some properties of the node that was created.
|
||||
$this->assertTrue($this->node->getType() == 'page', 'Node type is Basic page.');
|
||||
$dummy_title = 'Lorem ipsum';
|
||||
$this->assertNotEqual($dummy_title, $this->node->label(), "Dummy title doesn't equal node title.");
|
||||
|
||||
// Search for the dummy title with a GET query.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $dummy_title]]);
|
||||
$this->assertNoText($this->node->label(), 'Basic page node is not found with dummy title.');
|
||||
|
||||
// Search for the title of the node with a GET query.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $this->node->label()]]);
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with GET query.');
|
||||
|
||||
// Search for the title of the node with a POST query.
|
||||
$edit = ['or' => $this->node->label()];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with POST query.');
|
||||
|
||||
// Search by node type.
|
||||
$this->drupalPostForm('search/node', array_merge($edit, ['type[page]' => 'page']), t('Advanced search'));
|
||||
$this->assertText($this->node->label(), 'Basic page node is found with POST query and type:page.');
|
||||
|
||||
$this->drupalPostForm('search/node', array_merge($edit, ['type[article]' => 'article']), t('Advanced search'));
|
||||
$this->assertText('search yielded no results', 'Article node is not found with POST query and type:article.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that after submitting the advanced search form, the form is refilled.
|
||||
*/
|
||||
public function testFormRefill() {
|
||||
$edit = [
|
||||
'keys' => 'cat',
|
||||
'or' => 'dog gerbil',
|
||||
'phrase' => 'pets are nice',
|
||||
'negative' => 'fish snake',
|
||||
'type[page]' => 'page',
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
|
||||
// Test that the encoded query appears in the page title. Only test the
|
||||
// part not including the quote, because assertText() cannot seem to find
|
||||
// the quote marks successfully.
|
||||
$this->assertText('Search for cat dog OR gerbil -fish -snake');
|
||||
|
||||
// Verify that all of the form fields are filled out.
|
||||
foreach ($edit as $key => $value) {
|
||||
if ($key != 'type[page]') {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertTrue(isset($elements[0]) && $elements[0]['value'] == $value, "Field $key is set to $value");
|
||||
}
|
||||
else {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertTrue(isset($elements[0]) && !empty($elements[0]['checked']), "Field $key is checked");
|
||||
}
|
||||
}
|
||||
|
||||
// Now test by submitting the or/not part of the query in the main
|
||||
// search box, and verify that the advanced form is not filled out.
|
||||
// (It shouldn't be filled out unless you submit values in those fields.)
|
||||
$edit2 = ['keys' => 'cat dog OR gerbil -fish -snake'];
|
||||
$this->drupalPostForm('search/node', $edit2, t('Advanced search'));
|
||||
$this->assertText('Search for cat dog OR gerbil -fish -snake');
|
||||
foreach ($edit as $key => $value) {
|
||||
if ($key != 'type[page]') {
|
||||
$elements = $this->xpath('//input[@name=:name]', [':name' => $key]);
|
||||
$this->assertFalse(isset($elements[0]) && $elements[0]['value'] == $value, "Field $key is not set to $value");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Tests if the search form block is available.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchBlockTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$admin_user = $this->drupalCreateUser(['administer blocks', 'search content']);
|
||||
$this->drupalLogin($admin_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the search form block can be placed and works.
|
||||
*/
|
||||
public function testSearchFormBlock() {
|
||||
|
||||
// Test availability of the search block in the admin "Place blocks" list.
|
||||
$this->drupalGet('admin/structure/block');
|
||||
$this->clickLinkPartialName('Place block');
|
||||
$this->assertLinkByHref('/admin/structure/block/add/search_form_block/classy', 0,
|
||||
'Did not find the search block in block candidate list.');
|
||||
|
||||
$block = $this->drupalPlaceBlock('search_form_block');
|
||||
|
||||
$this->drupalGet('');
|
||||
$this->assertText($block->label(), 'Block title was found.');
|
||||
|
||||
// Check that name attribute is not empty.
|
||||
$pattern = "//input[@type='submit' and @name='']";
|
||||
$elements = $this->xpath($pattern);
|
||||
$this->assertTrue(empty($elements), 'The search input field does not have empty name attribute.');
|
||||
|
||||
// Test a normal search via the block form, from the front page.
|
||||
$terms = ['keys' => 'test'];
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Test a search from the block on a 404 page.
|
||||
$this->drupalGet('foo');
|
||||
$this->assertResponse(404);
|
||||
$this->submitGetForm(NULL, $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
$visibility = $block->getVisibility();
|
||||
$visibility['request_path']['pages'] = 'search';
|
||||
$block->setVisibilityConfig('request_path', $visibility['request_path']);
|
||||
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Your search yielded no results');
|
||||
|
||||
// Confirm that the form submits to the default search page.
|
||||
/** @var $search_page_repository \Drupal\search\SearchPageRepositoryInterface */
|
||||
$search_page_repository = \Drupal::service('search.search_page_repository');
|
||||
$entity_id = $search_page_repository->getDefaultSearchPage();
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, [], ['query' => ['keys' => $terms['keys']], 'absolute' => TRUE]),
|
||||
'Submitted to correct URL.'
|
||||
);
|
||||
|
||||
// Test an empty search via the block form, from the front page.
|
||||
$terms = ['keys' => ''];
|
||||
$this->submitGetForm('', $terms, t('Search'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertText('Please enter some keywords');
|
||||
|
||||
// Confirm that the user is redirected to the search page, when form is
|
||||
// submitted empty.
|
||||
$this->assertEqual(
|
||||
$this->getUrl(),
|
||||
\Drupal::url('search.view_' . $entity_id, [], ['query' => ['keys' => ''], 'absolute' => TRUE]),
|
||||
'Redirected to correct URL.'
|
||||
);
|
||||
|
||||
// Test that after entering a too-short keyword in the form, you can then
|
||||
// search again with a longer keyword. First test using the block form.
|
||||
$this->submitGetForm('node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->assertText('You must include at least one keyword to match in the content', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->submitGetForm(NULL, ['keys' => $this->randomMachineName()], t('Search'), 'search-block-form');
|
||||
$this->assertNoText('You must include at least one keyword to match in the content', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Same test again, using the search page form for the second search this
|
||||
// time.
|
||||
$this->submitGetForm('node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->drupalPostForm(NULL, ['keys' => $this->randomMachineName()], t('Search'), [], [], 'search-form');
|
||||
$this->assertNoText('You must include at least one keyword to match in the content', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,354 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\user\RoleInterface;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
|
||||
/**
|
||||
* Tests integration searching comments.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchCommentTest extends SearchTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['filter', 'node', 'comment'];
|
||||
|
||||
/**
|
||||
* Test subject for comments.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $commentSubject;
|
||||
|
||||
/**
|
||||
* ID for the administrator role.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $adminRole;
|
||||
|
||||
/**
|
||||
* A user with various administrative permissions.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $adminUser;
|
||||
|
||||
/**
|
||||
* Test node for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
'weight' => 1,
|
||||
'filters' => [],
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Create and log in an administrative user having access to the Full HTML
|
||||
// text format.
|
||||
$permissions = [
|
||||
'administer filters',
|
||||
$full_html_format->getPermissionName(),
|
||||
'administer permissions',
|
||||
'create page content',
|
||||
'post comments',
|
||||
'skip comment approval',
|
||||
'access comments',
|
||||
];
|
||||
$this->adminUser = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($this->adminUser);
|
||||
// Add a comment field.
|
||||
$this->addDefaultCommentField('node', 'article');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that comments are rendered using proper format in search results.
|
||||
*/
|
||||
public function testSearchResultsComment() {
|
||||
$node_storage = $this->container->get('entity.manager')->getStorage('node');
|
||||
// Create basic_html format that escapes all HTML.
|
||||
$basic_html_format = FilterFormat::create([
|
||||
'format' => 'basic_html',
|
||||
'name' => 'Basic HTML',
|
||||
'weight' => 1,
|
||||
'filters' => [
|
||||
'filter_html_escape' => ['status' => 1],
|
||||
],
|
||||
'roles' => [RoleInterface::AUTHENTICATED_ID],
|
||||
]);
|
||||
$basic_html_format->save();
|
||||
|
||||
$comment_body = 'Test comment body';
|
||||
|
||||
// Make preview optional.
|
||||
$field = FieldConfig::loadByName('node', 'article', 'comment');
|
||||
$field->setSetting('preview', DRUPAL_OPTIONAL);
|
||||
$field->save();
|
||||
|
||||
// Allow anonymous users to search content.
|
||||
$edit = [
|
||||
RoleInterface::ANONYMOUS_ID . '[search content]' => 1,
|
||||
RoleInterface::ANONYMOUS_ID . '[access comments]' => 1,
|
||||
RoleInterface::ANONYMOUS_ID . '[post comments]' => 1,
|
||||
];
|
||||
$this->drupalPostForm('admin/people/permissions', $edit, t('Save permissions'));
|
||||
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode(['type' => 'article']);
|
||||
// Post a comment using 'Full HTML' text format.
|
||||
$edit_comment = [];
|
||||
$edit_comment['subject[0][value]'] = 'Test comment subject';
|
||||
$edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>';
|
||||
$full_html_format_id = 'full_html';
|
||||
$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 = [];
|
||||
$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 = [];
|
||||
$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();
|
||||
|
||||
// Search for the comment subject.
|
||||
$edit = [
|
||||
'keys' => "'" . $edit_comment['subject[0][value]'] . "'",
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$node_storage->resetCache([$node->id()]);
|
||||
$node2 = $node_storage->load($node->id());
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
$this->assertText($edit_comment['subject[0][value]'], 'Comment subject found in search results.');
|
||||
|
||||
// Search for the comment body.
|
||||
$edit = [
|
||||
'keys' => "'" . $comment_body . "'",
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Search'));
|
||||
$this->assertText($node2->label(), 'Node found in search results.');
|
||||
|
||||
// Verify that comment is rendered using proper format.
|
||||
$this->assertText($comment_body, 'Comment body text found in search results.');
|
||||
$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 = [
|
||||
'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);
|
||||
$node->save();
|
||||
|
||||
// Invoke search index update.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
||||
// Search for $title.
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText(t('Your search yielded no results.'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify access rules for comment indexing with different permissions.
|
||||
*/
|
||||
public function testSearchResultsCommentAccess() {
|
||||
$comment_body = 'Test comment body';
|
||||
$this->commentSubject = 'Test comment subject';
|
||||
$roles = $this->adminUser->getRoles(TRUE);
|
||||
$this->adminRole = $roles[0];
|
||||
|
||||
// Create a node.
|
||||
// Make preview optional.
|
||||
$field = FieldConfig::loadByName('node', 'article', 'comment');
|
||||
$field->setSetting('preview', DRUPAL_OPTIONAL);
|
||||
$field->save();
|
||||
$this->node = $this->drupalCreateNode(['type' => 'article']);
|
||||
|
||||
// Post a comment using 'Full HTML' text format.
|
||||
$edit_comment = [];
|
||||
$edit_comment['subject[0][value]'] = $this->commentSubject;
|
||||
$edit_comment['comment_body[0][value]'] = '<h1>' . $comment_body . '</h1>';
|
||||
$this->drupalPostForm('comment/reply/node/' . $this->node->id() . '/comment', $edit_comment, t('Save'));
|
||||
|
||||
$this->drupalLogout();
|
||||
$this->setRolePermissions(RoleInterface::ANONYMOUS_ID);
|
||||
$this->assertCommentAccess(FALSE, 'Anon user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::ANONYMOUS_ID, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Anon user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/people/permissions');
|
||||
|
||||
// Disable search access for authenticated user to test admin user.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, FALSE, FALSE);
|
||||
|
||||
$this->setRolePermissions($this->adminRole);
|
||||
$this->assertCommentAccess(FALSE, 'Admin user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->drupalGet('node/' . $this->node->id());
|
||||
$this->setRolePermissions($this->adminRole, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Admin user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID);
|
||||
$this->assertCommentAccess(FALSE, 'Authenticated user has search permission but no access comments permission, comments should not be indexed');
|
||||
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE);
|
||||
$this->assertCommentAccess(TRUE, 'Authenticated user has search permission and access comments permission, comments should be indexed');
|
||||
|
||||
// Verify that access comments permission is inherited from the
|
||||
// authenticated role.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, FALSE);
|
||||
$this->setRolePermissions($this->adminRole);
|
||||
$this->assertCommentAccess(TRUE, 'Admin user has search permission and no access comments permission, but comments should be indexed because admin user inherits authenticated user\'s permission to access comments');
|
||||
|
||||
// Verify that search content permission is inherited from the authenticated
|
||||
// role.
|
||||
$this->setRolePermissions(RoleInterface::AUTHENTICATED_ID, TRUE, TRUE);
|
||||
$this->setRolePermissions($this->adminRole, TRUE, FALSE);
|
||||
$this->assertCommentAccess(TRUE, 'Admin user has access comments permission and no search permission, but comments should be indexed because admin user inherits authenticated user\'s permission to search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permissions for role.
|
||||
*/
|
||||
public function setRolePermissions($rid, $access_comments = FALSE, $search_content = TRUE) {
|
||||
$permissions = [
|
||||
'access comments' => $access_comments,
|
||||
'search content' => $search_content,
|
||||
];
|
||||
user_role_change_permissions($rid, $permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search index and search for comment.
|
||||
*/
|
||||
public function assertCommentAccess($assume_access, $message) {
|
||||
// Invoke search index update.
|
||||
search_mark_for_reindex('node_search', $this->node->id());
|
||||
$this->cronRun();
|
||||
|
||||
// Search for the comment subject.
|
||||
$edit = [
|
||||
'keys' => "'" . $this->commentSubject . "'",
|
||||
];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
|
||||
if ($assume_access) {
|
||||
$expected_node_result = $this->assertText($this->node->label());
|
||||
$expected_comment_result = $this->assertText($this->commentSubject);
|
||||
}
|
||||
else {
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that 'add new comment' does not appear in search results or index.
|
||||
*/
|
||||
public function testAddNewComment() {
|
||||
// Create a node with a short body.
|
||||
$settings = [
|
||||
'type' => 'article',
|
||||
'title' => 'short title',
|
||||
'body' => [['value' => 'short body text']],
|
||||
];
|
||||
|
||||
$user = $this->drupalCreateUser([
|
||||
'search content',
|
||||
'create article content',
|
||||
'access content',
|
||||
'post comments',
|
||||
'access comments',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
// Verify that if you view the node on its own page, 'add new comment'
|
||||
// is there.
|
||||
$this->drupalGet('node/' . $node->id());
|
||||
$this->assertText(t('Add new comment'));
|
||||
|
||||
// Run cron to index this page.
|
||||
$this->drupalLogout();
|
||||
$this->cronRun();
|
||||
|
||||
// Search for 'comment'. Should be no results.
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalPostForm('search/node', ['keys' => 'comment'], t('Search'));
|
||||
$this->assertText(t('Your search yielded no results'));
|
||||
|
||||
// Search for the node title. Should be found, and 'Add new comment' should
|
||||
// not be part of the search snippet.
|
||||
$this->drupalPostForm('search/node', ['keys' => 'short'], t('Search'));
|
||||
$this->assertText($node->label(), 'Search for keyword worked');
|
||||
$this->assertNoText(t('Add new comment'));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,404 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
|
||||
/**
|
||||
* Verify the search config settings form.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchConfigSettingsFormTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['block', 'search_extra_type', 'test_page_test'];
|
||||
|
||||
/**
|
||||
* User who can search and administer search.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchUser;
|
||||
|
||||
/**
|
||||
* Node indexed for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $searchNode;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Log in as a user that can create and search content.
|
||||
$this->searchUser = $this->drupalCreateUser(['search content', 'administer search', 'administer nodes', 'bypass node access', 'access user profiles', 'administer users', 'administer blocks', 'access site reports']);
|
||||
$this->drupalLogin($this->searchUser);
|
||||
|
||||
// Add a single piece of content and index it.
|
||||
$node = $this->drupalCreateNode();
|
||||
$this->searchNode = $node;
|
||||
// Link the node to itself to test that it's only indexed once. The content
|
||||
// also needs the word "pizza" so we can use it as the search keyword.
|
||||
$body_key = 'body[0][value]';
|
||||
$edit[$body_key] = \Drupal::l($node->label(), $node->urlInfo()) . ' pizza sandwich';
|
||||
$this->drupalPostForm('node/' . $node->id() . '/edit', $edit, t('Save and keep published'));
|
||||
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Enable the search block.
|
||||
$this->drupalPlaceBlock('search_form_block');
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the search settings form.
|
||||
*/
|
||||
public function testSearchSettingsPage() {
|
||||
|
||||
// Test that the settings form displays the correct count of items left to index.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('There are @count items left to index.', ['@count' => 0]));
|
||||
|
||||
// Test the re-index button.
|
||||
$this->drupalPostForm('admin/config/search/pages', [], t('Re-index site'));
|
||||
$this->assertText(t('Are you sure you want to re-index the site'));
|
||||
$this->drupalPostForm('admin/config/search/pages/reindex', [], t('Re-index site'));
|
||||
$this->assertText(t('All search indexes will be rebuilt'));
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('There is 1 item left to index.'));
|
||||
|
||||
// Test that the form saves with the default values.
|
||||
$this->drupalPostForm('admin/config/search/pages', [], t('Save configuration'));
|
||||
$this->assertText(t('The configuration options have been saved.'), 'Form saves with the default values.');
|
||||
|
||||
// Test that the form does not save with an invalid word length.
|
||||
$edit = [
|
||||
'minimum_word_size' => $this->randomMachineName(3),
|
||||
];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$this->assertNoText(t('The configuration options have been saved.'), 'Form does not save with an invalid word length.');
|
||||
|
||||
// Test logging setting. It should be off by default.
|
||||
$text = $this->randomMachineName(5);
|
||||
$this->drupalPostForm('search/node', ['keys' => $text], t('Search'));
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertNoLink('Searched Content for ' . $text . '.', 'Search was not logged');
|
||||
|
||||
// Turn on logging.
|
||||
$edit = ['logging' => TRUE];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$text = $this->randomMachineName(5);
|
||||
$this->drupalPostForm('search/node', ['keys' => $text], t('Search'));
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertLink('Searched Content for ' . $text . '.', 0, 'Search was logged');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies plugin-supplied settings form.
|
||||
*/
|
||||
public function testSearchModuleSettingsPage() {
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->clickLink(t('Edit'), 1);
|
||||
|
||||
// Ensure that the default setting was picked up from the default config
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="bi" and @selected="selected"]'), 'Module specific settings are picked up from the default config');
|
||||
|
||||
// Change extra type setting and also modify a common search setting.
|
||||
$edit = [
|
||||
'extra_type_settings[boost]' => 'ii',
|
||||
];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save search page'));
|
||||
|
||||
// Ensure that the modifications took effect.
|
||||
$this->assertRaw(t('The %label search page has been updated.', ['%label' => 'Dummy search type']));
|
||||
$this->drupalGet('admin/config/search/pages/manage/dummy_search_type');
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-extra-type-settings-boost"]//option[@value="ii" and @selected="selected"]'), 'Module specific settings can be changed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that you can disable individual search plugins.
|
||||
*/
|
||||
public function testSearchModuleDisabling() {
|
||||
// Array of search plugins to test: 'keys' are the keywords to search for,
|
||||
// and 'text' is the text to assert is on the results page.
|
||||
$plugin_info = [
|
||||
'node_search' => [
|
||||
'keys' => 'pizza',
|
||||
'text' => $this->searchNode->label(),
|
||||
],
|
||||
'user_search' => [
|
||||
'keys' => $this->searchUser->getUsername(),
|
||||
'text' => $this->searchUser->getEmail(),
|
||||
],
|
||||
'dummy_search_type' => [
|
||||
'keys' => 'foo',
|
||||
'text' => 'Dummy search snippet to display',
|
||||
],
|
||||
];
|
||||
$plugins = array_keys($plugin_info);
|
||||
/** @var $entities \Drupal\search\SearchPageInterface[] */
|
||||
$entities = SearchPage::loadMultiple();
|
||||
// Disable all of the search pages.
|
||||
foreach ($entities as $entity) {
|
||||
$entity->disable()->save();
|
||||
}
|
||||
|
||||
// Test each plugin if it's enabled as the only search plugin.
|
||||
foreach ($entities as $entity_id => $entity) {
|
||||
$this->setDefaultThroughUi($entity_id);
|
||||
|
||||
// Run a search from the correct search URL.
|
||||
$info = $plugin_info[$entity_id];
|
||||
$this->drupalGet('search/' . $entity->getPath(), ['query' => ['keys' => $info['keys']]]);
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoText('no results', $entity->label() . ' search found results');
|
||||
$this->assertText($info['text'], 'Correct search text found');
|
||||
|
||||
// Verify that other plugin search tab labels are not visible.
|
||||
foreach ($plugins as $other) {
|
||||
if ($other != $entity_id) {
|
||||
$label = $entities[$other]->label();
|
||||
$this->assertNoText($label, $label . ' search tab is not shown');
|
||||
}
|
||||
}
|
||||
|
||||
// Run a search from the search block on the node page. Verify you get
|
||||
// to this plugin's search results page.
|
||||
$terms = ['keys' => $info['keys']];
|
||||
$this->submitGetForm('node', $terms, t('Search'));
|
||||
$current = $this->getURL();
|
||||
$expected = \Drupal::url('search.view_' . $entity->id(), [], ['query' => ['keys' => $info['keys']], 'absolute' => TRUE]);
|
||||
$this->assertEqual( $current, $expected, 'Block redirected to right search page');
|
||||
|
||||
// Try an invalid search path, which should 404.
|
||||
$this->drupalGet('search/not_a_plugin_path');
|
||||
$this->assertResponse(404);
|
||||
|
||||
$entity->disable()->save();
|
||||
}
|
||||
|
||||
// Set the node search as default.
|
||||
$this->setDefaultThroughUi('node_search');
|
||||
|
||||
// Test with all search plugins enabled. When you go to the search
|
||||
// page or run search, all plugins should be shown.
|
||||
foreach ($entities as $entity) {
|
||||
$entity->enable()->save();
|
||||
}
|
||||
|
||||
\Drupal::service('router.builder')->rebuild();
|
||||
|
||||
$paths = [
|
||||
['path' => 'search/node', 'options' => ['query' => ['keys' => 'pizza']]],
|
||||
['path' => 'search/node', 'options' => []],
|
||||
];
|
||||
|
||||
foreach ($paths as $item) {
|
||||
$this->drupalGet($item['path'], $item['options']);
|
||||
foreach ($plugins as $entity_id) {
|
||||
$label = $entities[$entity_id]->label();
|
||||
$this->assertText($label, format_string('%label search tab is shown', ['%label' => $label]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the ordering of search pages on a clean install.
|
||||
*/
|
||||
public function testDefaultSearchPageOrdering() {
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical((string) $elements[0]['href'], \Drupal::url('search.view_node_search'));
|
||||
$this->assertIdentical((string) $elements[1]['href'], \Drupal::url('search.view_dummy_search_type'));
|
||||
$this->assertIdentical((string) $elements[2]['href'], \Drupal::url('search.view_user_search'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests multiple search pages of the same type.
|
||||
*/
|
||||
public function testMultipleSearchPages() {
|
||||
$this->assertDefaultSearch('node_search', 'The default page is set to the installer default.');
|
||||
$search_storage = \Drupal::entityManager()->getStorage('search_page');
|
||||
$entities = $search_storage->loadMultiple();
|
||||
$search_storage->delete($entities);
|
||||
$this->assertDefaultSearch(FALSE);
|
||||
|
||||
// Ensure that no search pages are configured.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->assertText(t('No search pages have been configured.'));
|
||||
|
||||
// Add a search page.
|
||||
$edit = [];
|
||||
$edit['search_type'] = 'search_extra_type_search';
|
||||
$this->drupalPostForm(NULL, $edit, t('Add search page'));
|
||||
$this->assertTitle('Add new search page | Drupal');
|
||||
|
||||
$first = [];
|
||||
$first['label'] = $this->randomString();
|
||||
$first_id = $first['id'] = strtolower($this->randomMachineName(8));
|
||||
$first['path'] = strtolower($this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $first, t('Save'));
|
||||
$this->assertDefaultSearch($first_id, 'The default page matches the only search page.');
|
||||
$this->assertRaw(t('The %label search page has been added.', ['%label' => $first['label']]));
|
||||
|
||||
// Attempt to add a search page with an existing path.
|
||||
$edit = [];
|
||||
$edit['search_type'] = 'search_extra_type_search';
|
||||
$this->drupalPostForm(NULL, $edit, t('Add search page'));
|
||||
$edit = [];
|
||||
$edit['label'] = $this->randomString();
|
||||
$edit['id'] = strtolower($this->randomMachineName(8));
|
||||
$edit['path'] = $first['path'];
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
$this->assertText(t('The search page path must be unique.'));
|
||||
|
||||
// Add a second search page.
|
||||
$second = [];
|
||||
$second['label'] = $this->randomString();
|
||||
$second_id = $second['id'] = strtolower($this->randomMachineName(8));
|
||||
$second['path'] = strtolower($this->randomMachineName(8));
|
||||
$this->drupalPostForm(NULL, $second, t('Save'));
|
||||
$this->assertDefaultSearch($first_id, 'The default page matches the only search page.');
|
||||
|
||||
// Ensure both search pages have their tabs displayed.
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical((string) $elements[0]['href'], Url::fromRoute('search.view_' . $first_id)->toString());
|
||||
$this->assertIdentical((string) $elements[1]['href'], Url::fromRoute('search.view_' . $second_id)->toString());
|
||||
|
||||
// Switch the weight of the search pages and check the order of the tabs.
|
||||
$edit = [
|
||||
'entities[' . $first_id . '][weight]' => 10,
|
||||
'entities[' . $second_id . '][weight]' => -10,
|
||||
];
|
||||
$this->drupalPostForm('admin/config/search/pages', $edit, t('Save configuration'));
|
||||
$this->drupalGet('search');
|
||||
$elements = $this->xpath('//*[contains(@class, :class)]//a', [':class' => 'tabs primary']);
|
||||
$this->assertIdentical((string) $elements[0]['href'], Url::fromRoute('search.view_' . $second_id)->toString());
|
||||
$this->assertIdentical((string) $elements[1]['href'], Url::fromRoute('search.view_' . $first_id)->toString());
|
||||
|
||||
// Check the initial state of the search pages.
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
$this->verifySearchPageOperations($first_id, TRUE, FALSE, FALSE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, TRUE, TRUE, FALSE);
|
||||
|
||||
// Change the default search page.
|
||||
$this->clickLink(t('Set as default'));
|
||||
$this->assertRaw(t('The default search page is now %label. Be sure to check the ordering of your search pages.', ['%label' => $second['label']]));
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, TRUE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Disable the first search page.
|
||||
$this->clickLink(t('Disable'));
|
||||
$this->assertResponse(200);
|
||||
$this->assertNoLink(t('Disable'));
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, FALSE, TRUE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Enable the first search page.
|
||||
$this->clickLink(t('Enable'));
|
||||
$this->assertResponse(200);
|
||||
$this->verifySearchPageOperations($first_id, TRUE, TRUE, TRUE, FALSE);
|
||||
$this->verifySearchPageOperations($second_id, TRUE, FALSE, FALSE, FALSE);
|
||||
|
||||
// Test deleting.
|
||||
$this->clickLink(t('Delete'));
|
||||
$this->assertRaw(t('Are you sure you want to delete the search page %label?', ['%label' => $first['label']]));
|
||||
$this->drupalPostForm(NULL, [], t('Delete'));
|
||||
$this->assertRaw(t('The search page %label has been deleted.', ['%label' => $first['label']]));
|
||||
$this->verifySearchPageOperations($first_id, FALSE, FALSE, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the enable/disable/default routes are protected from CSRF.
|
||||
*/
|
||||
public function testRouteProtection() {
|
||||
// Ensure that the enable and disable routes are protected.
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/enable');
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/disable');
|
||||
$this->assertResponse(403);
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search/set-default');
|
||||
$this->assertResponse(403);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the search page operations match expectations.
|
||||
*
|
||||
* @param string $id
|
||||
* The search page ID to check.
|
||||
* @param bool $edit
|
||||
* Whether the edit link is expected.
|
||||
* @param bool $delete
|
||||
* Whether the delete link is expected.
|
||||
* @param bool $disable
|
||||
* Whether the disable link is expected.
|
||||
* @param bool $enable
|
||||
* Whether the enable link is expected.
|
||||
*/
|
||||
protected function verifySearchPageOperations($id, $edit, $delete, $disable, $enable) {
|
||||
if ($edit) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id");
|
||||
}
|
||||
if ($delete) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/delete");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/delete");
|
||||
}
|
||||
if ($disable) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/disable");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/disable");
|
||||
}
|
||||
if ($enable) {
|
||||
$this->assertLinkByHref("admin/config/search/pages/manage/$id/enable");
|
||||
}
|
||||
else {
|
||||
$this->assertNoLinkByHref("admin/config/search/pages/manage/$id/enable");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the default search page matches expectations.
|
||||
*
|
||||
* @param string $expected
|
||||
* The expected search page.
|
||||
* @param string $message
|
||||
* (optional) A message to display with the assertion.
|
||||
* @param string $group
|
||||
* (optional) The group this message is in.
|
||||
*/
|
||||
protected function assertDefaultSearch($expected, $message = '', $group = 'Other') {
|
||||
/** @var $search_page_repository \Drupal\search\SearchPageRepositoryInterface */
|
||||
$search_page_repository = \Drupal::service('search.search_page_repository');
|
||||
$this->assertIdentical($search_page_repository->getDefaultSearchPage(), $expected, $message, $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a search page as the default in the UI.
|
||||
*
|
||||
* @param string $entity_id
|
||||
* The search page entity ID to enable.
|
||||
*/
|
||||
protected function setDefaultThroughUi($entity_id) {
|
||||
$this->drupalGet('admin/config/search/pages');
|
||||
preg_match('|href="([^"]+' . $entity_id . '/set-default[^"]+)"|', $this->getRawContent(), $matches);
|
||||
|
||||
$this->drupalGet($this->getAbsoluteUrl($matches[1]));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Verifies that a form embedded in search results works.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchEmbedFormTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['search_embedded_form'];
|
||||
|
||||
/**
|
||||
* Node used for testing.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* Count of how many times the form has been submitted.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $submitCount = 0;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a user and a node, and update the search index.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'administer nodes']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
$this->node = $this->drupalCreateNode();
|
||||
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Set up a dummy initial count of times the form has been submitted.
|
||||
$this->submitCount = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->refreshVariables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the embedded form appears and can be submitted.
|
||||
*/
|
||||
public function testEmbeddedForm() {
|
||||
// First verify we can submit the form from the module's page.
|
||||
$this->drupalPostForm('search_embedded_form',
|
||||
['name' => 'John'],
|
||||
t('Send away'));
|
||||
$this->assertText(t('Test form was submitted'), 'Form message appears');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount + 1, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
|
||||
// Now verify that we can see and submit the form from the search results.
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $this->node->label()]]);
|
||||
$this->assertText(t('Your name'), 'Form is visible');
|
||||
$this->drupalPostForm(NULL,
|
||||
['name' => 'John'],
|
||||
t('Send away'));
|
||||
$this->assertText(t('Test form was submitted'), 'Form message appears');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount + 1, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
|
||||
// Now verify that if we submit the search form, it doesn't count as
|
||||
// our form being submitted.
|
||||
$this->drupalPostForm('search',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText(t('Test form was submitted'), 'Form message does not appear');
|
||||
$count = \Drupal::state()->get('search_embedded_form.submit_count');
|
||||
$this->assertEqual($this->submitCount, $count, 'Form submission count is correct');
|
||||
$this->submitCount = $count;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
|
||||
/**
|
||||
* Tests advanced search with different languages added.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchLanguageTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['language'];
|
||||
|
||||
/**
|
||||
* Array of nodes available to search.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $searchableNodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create and log in user.
|
||||
$test_user = $this->drupalCreateUser(['access content', 'search content', 'use advanced search', 'administer nodes', 'administer languages', 'access administration pages', 'administer site configuration']);
|
||||
$this->drupalLogin($test_user);
|
||||
|
||||
// Add a new language.
|
||||
ConfigurableLanguage::createFromLangcode('es')->save();
|
||||
|
||||
// Make the body field translatable. The title is already translatable by
|
||||
// definition. The parent class has already created the article and page
|
||||
// content types.
|
||||
$field_storage = FieldStorageConfig::loadByName('node', 'body');
|
||||
$field_storage->setTranslatable(TRUE);
|
||||
$field_storage->save();
|
||||
|
||||
// Create a few page nodes with multilingual body values.
|
||||
$default_format = filter_default_format();
|
||||
$nodes = [
|
||||
[
|
||||
'title' => 'First node en',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'en',
|
||||
],
|
||||
[
|
||||
'title' => 'Second node this is the Spanish title',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'es',
|
||||
],
|
||||
[
|
||||
'title' => 'Third node en',
|
||||
'type' => 'page',
|
||||
'body' => [['value' => $this->randomMachineName(32), 'format' => $default_format]],
|
||||
'langcode' => 'en',
|
||||
],
|
||||
];
|
||||
$this->searchableNodes = [];
|
||||
foreach ($nodes as $setting) {
|
||||
$this->searchableNodes[] = $this->drupalCreateNode($setting);
|
||||
}
|
||||
|
||||
// Add English translation to the second node.
|
||||
$translation = $this->searchableNodes[1]->addTranslation('en', ['title' => 'Second node en']);
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
$this->searchableNodes[1]->save();
|
||||
|
||||
// Add Spanish translation to the third node.
|
||||
$translation = $this->searchableNodes[2]->addTranslation('es', ['title' => 'Third node es']);
|
||||
$translation->body->value = $this->randomMachineName(32);
|
||||
$this->searchableNodes[2]->save();
|
||||
|
||||
// Update the index and then run the shutdown method.
|
||||
$plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
$plugin->updateIndex();
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
public function testLanguages() {
|
||||
// Add predefined language.
|
||||
$edit = ['predefined_langcode' => 'fr'];
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
$this->assertText('French', 'Language added successfully.');
|
||||
|
||||
// Now we should have languages displayed.
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertText(t('Languages'), 'Languages displayed to choose from.');
|
||||
$this->assertText(t('English'), 'English is a possible choice.');
|
||||
$this->assertText(t('French'), 'French is a possible choice.');
|
||||
|
||||
// Ensure selecting no language does not make the query different.
|
||||
$this->drupalPostForm('search/node', [], t('Advanced search'));
|
||||
$this->assertUrl(\Drupal::url('search.view_node_search', [], ['query' => ['keys' => ''], 'absolute' => TRUE]), [], 'Correct page redirection, no language filtering.');
|
||||
|
||||
// Pick French and ensure it is selected.
|
||||
$edit = ['language[fr]' => TRUE];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
// Get the redirected URL.
|
||||
$url = $this->getUrl();
|
||||
$parts = parse_url($url);
|
||||
$query_string = isset($parts['query']) ? rawurldecode($parts['query']) : '';
|
||||
$this->assertTrue(strpos($query_string, '=language:fr') !== FALSE, 'Language filter language:fr add to the query string.');
|
||||
|
||||
// Search for keyword node and language filter as Spanish.
|
||||
$edit = ['keys' => 'node', 'language[es]' => TRUE];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
// Check for Spanish results.
|
||||
$this->assertLink('Second node this is the Spanish title', 0, 'Second node Spanish title found in search results');
|
||||
$this->assertLink('Third node es', 0, 'Third node Spanish found in search results');
|
||||
// Ensure that results don't contain other language nodes.
|
||||
$this->assertNoLink('First node en', 'Search results do not contain first English node');
|
||||
$this->assertNoLink('Second node en', 'Search results do not contain second English node');
|
||||
$this->assertNoLink('Third node en', 'Search results do not contain third English node');
|
||||
|
||||
// Change the default language and delete English.
|
||||
$path = 'admin/config/regional/language';
|
||||
$this->drupalGet($path);
|
||||
$this->assertFieldChecked('edit-site-default-language-en', 'Default language updated.');
|
||||
$edit = [
|
||||
'site_default_language' => 'fr',
|
||||
];
|
||||
$this->drupalPostForm($path, $edit, t('Save configuration'));
|
||||
$this->assertNoFieldChecked('edit-site-default-language-en', 'Default language updated.');
|
||||
$this->drupalPostForm('admin/config/regional/language/delete/en', [], t('Delete'));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Tests search index is updated properly when nodes are removed or updated.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNodeUpdateAndDeletionTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = [];
|
||||
|
||||
/**
|
||||
* A user with permission to access and search content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
public $testUser;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a test user and log in.
|
||||
$this->testUser = $this->drupalCreateUser(['access content', 'search content']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the search index info is properly updated when a node changes.
|
||||
*/
|
||||
public function testSearchIndexUpdateOnNodeChange() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => 'Someone who says Ni!',
|
||||
'body' => [['value' => "We are the knights who say Ni!"]],
|
||||
'type' => 'page']);
|
||||
|
||||
$node_search_plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
// Update the search index.
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search the node to verify it appears in search results
|
||||
$edit = ['keys' => 'knights'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
|
||||
// Update the node
|
||||
$node->body->value = "We want a shrubbery!";
|
||||
$node->save();
|
||||
|
||||
// Run indexer again
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search again to verify the new text appears in test results.
|
||||
$edit = ['keys' => 'shrubbery'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the search index info is updated when a node is deleted.
|
||||
*/
|
||||
public function testSearchIndexUpdateOnNodeDeletion() {
|
||||
// Create a node.
|
||||
$node = $this->drupalCreateNode([
|
||||
'title' => 'No dragons here',
|
||||
'body' => [['value' => 'Again: No dragons here']],
|
||||
'type' => 'page']);
|
||||
|
||||
$node_search_plugin = $this->container->get('plugin.manager.search')->createInstance('node_search');
|
||||
// Update the search index.
|
||||
$node_search_plugin->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search the node to verify it appears in search results
|
||||
$edit = ['keys' => 'dragons'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText($node->label());
|
||||
|
||||
// Get the node info from the search index tables.
|
||||
$search_index_dataset = db_query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons'])
|
||||
->fetchField();
|
||||
$this->assertNotEqual($search_index_dataset, FALSE, t('Node info found on the search_index'));
|
||||
|
||||
// Delete the node.
|
||||
$node->delete();
|
||||
|
||||
// Check if the node info is gone from the search table.
|
||||
$search_index_dataset = db_query("SELECT sid FROM {search_index} WHERE type = 'node_search' AND word = :word", [':word' => 'dragons'])
|
||||
->fetchField();
|
||||
$this->assertFalse($search_index_dataset, t('Node info successfully removed from search_index'));
|
||||
|
||||
// Search again to verify the node doesn't appear anymore.
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertNoText($node->label());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Tests that numbers can be searched with more complex matching.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNumberMatchingTest extends SearchTestBase {
|
||||
/**
|
||||
* A user with permission to administer nodes.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $testUser;
|
||||
|
||||
/**
|
||||
* An array of strings containing numbers to use for testing.
|
||||
*
|
||||
* Define a group of numbers that should all match each other --
|
||||
* numbers with internal punctuation should match each other, as well
|
||||
* as numbers with and without leading zeros and leading/trailing
|
||||
* . and -.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $numbers = [
|
||||
'123456789',
|
||||
'12/34/56789',
|
||||
'12.3456789',
|
||||
'12-34-56789',
|
||||
'123,456,789',
|
||||
'-123456789',
|
||||
'0123456789',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of nodes created for testing purposes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->testUser = $this->drupalCreateUser(['search content', 'access content', 'administer nodes', 'access site reports']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
|
||||
foreach ($this->numbers as $num) {
|
||||
$info = [
|
||||
'body' => [['value' => $num]],
|
||||
'type' => 'page',
|
||||
'language' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
];
|
||||
$this->nodes[] = $this->drupalCreateNode($info);
|
||||
}
|
||||
|
||||
// Run cron to ensure the content is indexed.
|
||||
$this->cronRun();
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertText(t('Cron run completed'), 'Log shows cron run completed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all the numbers can be searched.
|
||||
*/
|
||||
public function testNumberSearching() {
|
||||
for ($i = 0; $i < count($this->numbers); $i++) {
|
||||
$node = $this->nodes[$i];
|
||||
|
||||
// Verify that the node title does not appear on the search page
|
||||
// with a dummy search.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText($node->label(), format_string('%number: node title not shown in dummy search', ['%number' => $i]));
|
||||
|
||||
// Now verify that we can find node i by searching for any of the
|
||||
// numbers.
|
||||
for ($j = 0; $j < count($this->numbers); $j++) {
|
||||
$number = $this->numbers[$j];
|
||||
// If the number is negative, remove the - sign, because - indicates
|
||||
// "not keyword" when searching.
|
||||
$number = ltrim($number, '-');
|
||||
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => $number],
|
||||
t('Search'));
|
||||
$this->assertText($node->label(), format_string('%i: node title shown (search found the node) in search for number %number', ['%i' => $i, '%number' => $number]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
||||
/**
|
||||
* Tests that numbers can be searched.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchNumbersTest extends SearchTestBase {
|
||||
/**
|
||||
* A user with permission to administer nodes.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $testUser;
|
||||
|
||||
/**
|
||||
* An array containing a series of "numbers" for testing purposes.
|
||||
*
|
||||
* Create content with various numbers in it.
|
||||
* Note: 50 characters is the current limit of the search index's word
|
||||
* field.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $numbers = [
|
||||
'ISBN' => '978-0446365383',
|
||||
'UPC' => '036000 291452',
|
||||
'EAN bar code' => '5901234123457',
|
||||
'negative' => '-123456.7890',
|
||||
'quoted negative' => '"-123456.7890"',
|
||||
'leading zero' => '0777777777',
|
||||
'tiny' => '111',
|
||||
'small' => '22222222222222',
|
||||
'medium' => '333333333333333333333333333',
|
||||
'large' => '444444444444444444444444444444444444444',
|
||||
'gigantic' => '5555555555555555555555555555555555555555555555555',
|
||||
'over fifty characters' => '666666666666666666666666666666666666666666666666666666666666',
|
||||
'date' => '01/02/2009',
|
||||
'commas' => '987,654,321',
|
||||
];
|
||||
|
||||
/**
|
||||
* An array of nodes created for testing purposes.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface[]
|
||||
*/
|
||||
protected $nodes;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->testUser = $this->drupalCreateUser(['search content', 'access content', 'administer nodes', 'access site reports']);
|
||||
$this->drupalLogin($this->testUser);
|
||||
|
||||
foreach ($this->numbers as $doc => $num) {
|
||||
$info = [
|
||||
'body' => [['value' => $num]],
|
||||
'type' => 'page',
|
||||
'language' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
|
||||
'title' => $doc . ' number',
|
||||
];
|
||||
$this->nodes[$doc] = $this->drupalCreateNode($info);
|
||||
}
|
||||
|
||||
// Run cron to ensure the content is indexed.
|
||||
$this->cronRun();
|
||||
$this->drupalGet('admin/reports/dblog');
|
||||
$this->assertText(t('Cron run completed'), 'Log shows cron run completed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that all the numbers can be searched.
|
||||
*/
|
||||
public function testNumberSearching() {
|
||||
$types = array_keys($this->numbers);
|
||||
|
||||
foreach ($types as $type) {
|
||||
$number = $this->numbers[$type];
|
||||
// If the number is negative, remove the - sign, because - indicates
|
||||
// "not keyword" when searching.
|
||||
$number = ltrim($number, '-');
|
||||
$node = $this->nodes[$type];
|
||||
|
||||
// Verify that the node title does not appear on the search page
|
||||
// with a dummy search.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => 'foo'],
|
||||
t('Search'));
|
||||
$this->assertNoText($node->label(), $type . ': node title not shown in dummy search');
|
||||
|
||||
// Verify that the node title does appear as a link on the search page
|
||||
// when searching for the number.
|
||||
$this->drupalPostForm('search/node',
|
||||
['keys' => $number],
|
||||
t('Search'));
|
||||
$this->assertText($node->label(), format_string('%type: node title shown (search found the node) in search for number %number.', ['%type' => $type, '%number' => $number]));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,216 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Core\Cache\Cache;
|
||||
|
||||
/**
|
||||
* Tests the search_page entity cache tags on the search results pages.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageCacheTagsTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $dumpHeaders = TRUE;
|
||||
|
||||
/**
|
||||
* A user with permission to search content.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchingUser;
|
||||
|
||||
/**
|
||||
* A node that is indexed by the search module.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$this->searchingUser = $this->drupalCreateUser(['search content', 'access user profiles']);
|
||||
|
||||
// Create a node and update the search index.
|
||||
$this->node = $this->drupalCreateNode(['title' => 'bike shed shop']);
|
||||
$this->node->setOwner($this->searchingUser);
|
||||
$this->node->save();
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the presence of the expected cache tag in various situations.
|
||||
*/
|
||||
public function testSearchText() {
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
|
||||
// Initial page for searching nodes.
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Node search results.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'bike shed';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shed shop');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node:1');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertCacheTag('rendered');
|
||||
$this->assertCacheTag('http_response');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Updating a node should invalidate the search plugin's index cache tag.
|
||||
$this->node->title = 'bike shop';
|
||||
$this->node->save();
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shop');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node:1');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertCacheTag('rendered');
|
||||
$this->assertCacheTag('http_response');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Deleting a node should invalidate the search plugin's index cache tag.
|
||||
$this->node->delete();
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('Your search yielded no results.');
|
||||
$this->assertCacheTag('config:search.page.node_search');
|
||||
$this->assertCacheTag('search_index');
|
||||
$this->assertCacheTag('search_index:node_search');
|
||||
$this->assertCacheTag('node_list');
|
||||
|
||||
// Initial page for searching users.
|
||||
$this->drupalGet('search/user');
|
||||
$this->assertCacheTag('config:search.page.user_search');
|
||||
$this->assertCacheTag('user_list');
|
||||
$this->assertNoCacheTag('search_index');
|
||||
$this->assertNoCacheTag('search_index:user_search');
|
||||
|
||||
// User search results.
|
||||
$edit['keys'] = $this->searchingUser->getUsername();
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->assertCacheTag('config:search.page.user_search');
|
||||
$this->assertCacheTag('user_list');
|
||||
$this->assertCacheTag('user:2');
|
||||
$this->assertNoCacheTag('search_index');
|
||||
$this->assertNoCacheTag('search_index:user_search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the presence of expected cache tags with referenced entities.
|
||||
*/
|
||||
public function testSearchTagsBubbling() {
|
||||
|
||||
// Install field UI and entity reference modules.
|
||||
$this->container->get('module_installer')->install(['field_ui', 'entity_reference']);
|
||||
$this->resetAll();
|
||||
|
||||
|
||||
// Creates a new content type that will have an entity reference.
|
||||
$type_name = 'entity_reference_test';
|
||||
$type = $this->drupalCreateContentType(['name' => $type_name, 'type' => $type_name]);
|
||||
|
||||
$bundle_path = 'admin/structure/types/manage/' . $type->id();
|
||||
|
||||
// Create test user.
|
||||
$admin_user = $this->drupalCreateUser([
|
||||
'access content',
|
||||
'create ' . $type_name . ' content',
|
||||
'administer node fields',
|
||||
'administer node display',
|
||||
|
||||
]);
|
||||
$this->drupalLogin($admin_user);
|
||||
|
||||
// First step: 'Add new field' on the 'Manage fields' page.
|
||||
$this->drupalGet($bundle_path . '/fields/add-field');
|
||||
$this->drupalPostForm(NULL, [
|
||||
'label' => 'Test label',
|
||||
'field_name' => 'test__ref',
|
||||
'new_storage_type' => 'entity_reference',
|
||||
], t('Save and continue'));
|
||||
|
||||
// Second step: 'Field settings' form.
|
||||
$this->drupalPostForm(NULL, [], t('Save field settings'));
|
||||
|
||||
// Create a new node of our newly created node type and fill in the entity
|
||||
// reference field.
|
||||
$edit = [
|
||||
'title[0][value]' => 'Llama shop',
|
||||
'field_test__ref[0][target_id]' => $this->node->getTitle()
|
||||
];
|
||||
$this->drupalPostForm('node/add/' . $type->id(), $edit, t('Save'));
|
||||
|
||||
// Test that the value of the entity reference field is shown.
|
||||
$this->drupalGet('node/2');
|
||||
$this->assertText('bike shed shop');
|
||||
|
||||
// Refresh the search index.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Log in with searching user again.
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
|
||||
// Default search cache tags.
|
||||
$default_search_tags = [
|
||||
'config:search.page.node_search',
|
||||
'search_index',
|
||||
'search_index:node_search',
|
||||
'http_response',
|
||||
'rendered',
|
||||
'node_list',
|
||||
];
|
||||
|
||||
// Node search results for shop, should return node:1 (bike shed shop) and
|
||||
// node:2 (Llama shop). The related authors cache tags should be visible as
|
||||
// well.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'shop';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('bike shed shop');
|
||||
$this->assertText('Llama shop');
|
||||
$expected_cache_tags = Cache::mergeTags($default_search_tags, [
|
||||
'node:1',
|
||||
'user:2',
|
||||
'node:2',
|
||||
'user:3',
|
||||
'node_view',
|
||||
'config:filter.format.plain_text',
|
||||
]);
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
|
||||
// Only get the new node in the search results, should result in node:1,
|
||||
// node:2 and user:3 as cache tags even though only node:1 is shown. This is
|
||||
// because node:2 is reference in node:1 as an entity reference.
|
||||
$edit = [];
|
||||
$edit['keys'] = 'Llama';
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('Llama shop');
|
||||
$expected_cache_tags = Cache::mergeTags($default_search_tags, [
|
||||
'node:1',
|
||||
'node:2',
|
||||
'user:3',
|
||||
'node_view',
|
||||
]);
|
||||
$this->assertCacheTags($expected_cache_tags);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,163 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\Component\Utility\Html;
|
||||
use Drupal\Component\Utility\Unicode;
|
||||
|
||||
/**
|
||||
* Tests the search help text and search page text.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPageTextTest extends SearchTestBase {
|
||||
/**
|
||||
* A user with permission to use advanced search.
|
||||
*
|
||||
* @var \Drupal\user\UserInterface
|
||||
*/
|
||||
protected $searchingUser;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public static $modules = ['block'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user.
|
||||
$this->searchingUser = $this->drupalCreateUser(['search content', 'access user profiles', 'use advanced search']);
|
||||
$this->drupalPlaceBlock('local_tasks_block');
|
||||
$this->drupalPlaceBlock('page_title_block');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for XSS in search module local task.
|
||||
*
|
||||
* This is a regression test for https://www.drupal.org/node/2338081
|
||||
*/
|
||||
public function testSearchLabelXSS() {
|
||||
$this->drupalLogin($this->drupalCreateUser(['administer search']));
|
||||
|
||||
$keys['label'] = '<script>alert("Dont Panic");</script>';
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $keys, t('Save search page'));
|
||||
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertEscaped($keys['label']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the failed search text, and various other text on the search page.
|
||||
*/
|
||||
public function testSearchText() {
|
||||
$this->drupalLogin($this->searchingUser);
|
||||
$this->drupalGet('search/node');
|
||||
$this->assertText(t('Enter your keywords'));
|
||||
$this->assertText(t('Search'));
|
||||
$this->assertTitle(t('Search') . ' | Drupal', 'Search page title is correct');
|
||||
|
||||
$edit = [];
|
||||
$search_terms = 'bike shed ' . $this->randomMachineName();
|
||||
$edit['keys'] = $search_terms;
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertText('search yielded no results');
|
||||
$this->assertText(t('Search'));
|
||||
$title_source = 'Search for @keywords | Drupal';
|
||||
$this->assertTitle(t($title_source, ['@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');
|
||||
|
||||
$this->clickLink('Search help');
|
||||
$this->assertText('Search help', 'Correct title is on search help page');
|
||||
$this->assertText('Use upper-case OR to get more results', 'Correct text is on content search help page');
|
||||
|
||||
// Search for a longer text, and see that it is in the title, truncated.
|
||||
$edit = [];
|
||||
$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, ['@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, Html::decodeEntities(t($title_source, ['@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)])), 'Search page title is correct');
|
||||
|
||||
$edit['keys'] = $this->searchingUser->getUsername();
|
||||
$this->drupalPostForm('search/user', $edit, t('Search'));
|
||||
$this->assertText(t('Search'));
|
||||
$this->assertTitle(t($title_source, ['@keywords' => Unicode::truncate($this->searchingUser->getUsername(), 60, TRUE, TRUE)]));
|
||||
|
||||
$this->clickLink('Search help');
|
||||
$this->assertText('Search help', 'Correct title is on search help page');
|
||||
$this->assertText('user names and partial user names', 'Correct text is on user search help page');
|
||||
|
||||
// Test that search keywords containing slashes are correctly loaded
|
||||
// from the GET params and displayed in the search form.
|
||||
$arg = $this->randomMachineName() . '/' . $this->randomMachineName();
|
||||
$this->drupalGet('search/node', ['query' => ['keys' => $arg]]);
|
||||
$input = $this->xpath("//input[@id='edit-keys' and @value='{$arg}']");
|
||||
$this->assertFalse(empty($input), 'Search keys with a / are correctly set as the default value in the search box.');
|
||||
|
||||
// Test a search input exceeding the limit of AND/OR combinations to test
|
||||
// the Denial-of-Service protection.
|
||||
$limit = $this->config('search.settings')->get('and_or_limit');
|
||||
$keys = [];
|
||||
for ($i = 0; $i < $limit + 1; $i++) {
|
||||
// Use a key of 4 characters to ensure we never generate 'AND' or 'OR'.
|
||||
$keys[] = $this->randomMachineName(4);
|
||||
if ($i % 2 == 0) {
|
||||
$keys[] = 'OR';
|
||||
}
|
||||
}
|
||||
$edit['keys'] = implode(' ', $keys);
|
||||
$this->drupalPostForm('search/node', $edit, t('Search'));
|
||||
$this->assertRaw(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', ['@count' => $limit]));
|
||||
|
||||
// Test that a search on Node or User with no keywords entered generates
|
||||
// the "Please enter some keywords" message.
|
||||
$this->drupalPostForm('search/node', [], t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on node page');
|
||||
$this->drupalPostForm('search/user', [], t('Search'));
|
||||
$this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on user page');
|
||||
|
||||
// Make sure the "Please enter some keywords" message is NOT displayed if
|
||||
// you use "or" words or phrases in Advanced Search.
|
||||
$this->drupalPostForm('search/node', ['or' => $this->randomMachineName() . ' ' . $this->randomMachineName()], t('Advanced search'));
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced OR keywords entered, no keywords message is not displayed on node page');
|
||||
$this->drupalPostForm('search/node', ['phrase' => '"' . $this->randomMachineName() . '" "' . $this->randomMachineName() . '"'], t('Advanced search'));
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With advanced phrase entered, no keywords message is not displayed on node page');
|
||||
|
||||
// Verify that if you search for a too-short keyword, you get the right
|
||||
// message, and that if after that you search for a longer keyword, you
|
||||
// do not still see the message.
|
||||
$this->drupalPostForm('search/node', ['keys' => $this->randomMachineName(1)], t('Search'));
|
||||
$this->assertText('You must include at least one keyword', 'Keyword message is displayed when searching for short word');
|
||||
$this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed');
|
||||
$this->drupalPostForm(NULL, ['keys' => $this->randomMachineName()], t('Search'));
|
||||
$this->assertNoText('You must include at least one keyword', 'Keyword message is not displayed when searching for long word after short word search');
|
||||
|
||||
// Test that if you search for a URL with .. in it, you still end up at
|
||||
// the search page. See issue https://www.drupal.org/node/890058.
|
||||
$this->drupalPostForm('search/node', ['keys' => '../../admin'], t('Search'));
|
||||
$this->assertResponse(200, 'Searching for ../../admin with non-admin user does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for ../../admin with non-admin user gives you a no search results page');
|
||||
|
||||
// Test that if you search for a URL starting with "./", you still end up
|
||||
// at the search page. See issue https://www.drupal.org/node/1421560.
|
||||
$this->drupalPostForm('search/node', ['keys' => '.something'], t('Search'));
|
||||
$this->assertResponse(200, 'Searching for .something does not lead to a 403 error');
|
||||
$this->assertText('no results', 'Searching for .something gives you a no search results page');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Tests that the search preprocessing uses the correct language code.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchPreprocessLangcodeTest extends SearchTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['search_langcode_test'];
|
||||
|
||||
/**
|
||||
* Test node for searching.
|
||||
*
|
||||
* @var \Drupal\node\NodeInterface
|
||||
*/
|
||||
protected $node;
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$web_user = $this->drupalCreateUser([
|
||||
'create page content',
|
||||
'edit own page content',
|
||||
'search content',
|
||||
'use advanced search',
|
||||
]);
|
||||
$this->drupalLogin($web_user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that hook_search_preprocess() returns the correct langcode.
|
||||
*/
|
||||
public function testPreprocessLangcode() {
|
||||
// Create a node.
|
||||
$this->node = $this->drupalCreateNode(['body' => [[]], 'langcode' => 'en']);
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
|
||||
// Search for the additional text that is added by the preprocess
|
||||
// function. If you search for text that is in the node, preprocess is
|
||||
// not invoked on the node during the search excerpt generation.
|
||||
$edit = ['or' => 'Additional text'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
|
||||
// Checks if the langcode message has been set by hook_search_preprocess().
|
||||
$this->assertText('Langcode Preprocess Test: en');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests stemming for hook_search_preprocess().
|
||||
*/
|
||||
public function testPreprocessStemming() {
|
||||
// Create a node.
|
||||
$this->node = $this->drupalCreateNode([
|
||||
'title' => 'we are testing',
|
||||
'body' => [[]],
|
||||
'langcode' => 'en',
|
||||
]);
|
||||
|
||||
// First update the index. This does the initial processing.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
|
||||
// Then, run the shutdown function. Testing is a unique case where indexing
|
||||
// and searching has to happen in the same request, so running the shutdown
|
||||
// function manually is needed to finish the indexing process.
|
||||
search_update_totals();
|
||||
|
||||
// Search for the title of the node with a POST query.
|
||||
$edit = ['or' => 'testing'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
|
||||
// Check if the node has been found.
|
||||
$this->assertText('Search results');
|
||||
$this->assertText('we are testing');
|
||||
|
||||
// Search for the same node using a different query.
|
||||
$edit = ['or' => 'test'];
|
||||
$this->drupalPostForm('search/node', $edit, t('Advanced search'));
|
||||
|
||||
// Check if the node has been found.
|
||||
$this->assertText('Search results');
|
||||
$this->assertText('we are testing');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
/**
|
||||
* Tests that the node search query can be altered via the query alter hook.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchQueryAlterTest extends SearchTestBase {
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['search_query_alter'];
|
||||
|
||||
/**
|
||||
* Tests that the query alter works.
|
||||
*/
|
||||
public function testQueryAlter() {
|
||||
// Log in with sufficient privileges.
|
||||
$this->drupalLogin($this->drupalCreateUser(['create page content', 'search content']));
|
||||
|
||||
// Create a node and an article with the same keyword. The query alter
|
||||
// test module will alter the query so only articles should be returned.
|
||||
$data = [
|
||||
'type' => 'page',
|
||||
'title' => 'test page',
|
||||
'body' => [['value' => 'pizza']],
|
||||
];
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
$data['type'] = 'article';
|
||||
$data['title'] = 'test article';
|
||||
$this->drupalCreateNode($data);
|
||||
|
||||
// Update the search index.
|
||||
$this->container->get('plugin.manager.search')->createInstance('node_search')->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
// Search for the body keyword 'pizza'.
|
||||
$this->drupalPostForm('search/node', ['keys' => 'pizza'], t('Search'));
|
||||
// The article should be there but not the page.
|
||||
$this->assertText('article', 'Article is in search results');
|
||||
$this->assertNoText('page', 'Page is not in search results');
|
||||
}
|
||||
|
||||
}
|
|
@ -1,279 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
|
||||
use Drupal\comment\Tests\CommentTestTrait;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\filter\Entity\FilterFormat;
|
||||
use Drupal\search\Entity\SearchPage;
|
||||
|
||||
/**
|
||||
* Indexes content and tests ranking factors.
|
||||
*
|
||||
* @group search
|
||||
*/
|
||||
class SearchRankingTest extends SearchTestBase {
|
||||
|
||||
use CommentTestTrait;
|
||||
|
||||
/**
|
||||
* The node search page.
|
||||
*
|
||||
* @var \Drupal\search\SearchPageInterface
|
||||
*/
|
||||
protected $nodeSearch;
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['statistics', 'comment'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a plugin instance.
|
||||
$this->nodeSearch = SearchPage::load('node_search');
|
||||
|
||||
// Log in with sufficient privileges.
|
||||
$this->drupalLogin($this->drupalCreateUser(['post comments', 'skip comment approval', 'create page content', 'administer search']));
|
||||
}
|
||||
|
||||
public function testRankings() {
|
||||
// Add a comment field.
|
||||
$this->addDefaultCommentField('node', 'page');
|
||||
|
||||
// Build a list of the rankings to test.
|
||||
$node_ranks = ['sticky', 'promote', 'relevance', 'recent', 'comments', 'views'];
|
||||
|
||||
// Create nodes for testing.
|
||||
$nodes = [];
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$settings = [
|
||||
'type' => 'page',
|
||||
'comment' => [[
|
||||
'status' => CommentItemInterface::HIDDEN,
|
||||
]],
|
||||
'title' => 'Drupal rocks',
|
||||
'body' => [['value' => "Drupal's search rocks"]],
|
||||
// Node is one day old.
|
||||
'created' => REQUEST_TIME - 24 * 3600,
|
||||
'sticky' => 0,
|
||||
'promote' => 0,
|
||||
];
|
||||
foreach ([0, 1] as $num) {
|
||||
if ($num == 1) {
|
||||
switch ($node_rank) {
|
||||
case 'sticky':
|
||||
case 'promote':
|
||||
$settings[$node_rank] = 1;
|
||||
break;
|
||||
case 'relevance':
|
||||
$settings['body'][0]['value'] .= " really rocks";
|
||||
break;
|
||||
case 'recent':
|
||||
// Node is 1 hour hold.
|
||||
$settings['created'] = REQUEST_TIME - 3600;
|
||||
break;
|
||||
case 'comments':
|
||||
$settings['comment'][0]['status'] = CommentItemInterface::OPEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$nodes[$node_rank][$num] = $this->drupalCreateNode($settings);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a comment to one of the nodes.
|
||||
$edit = [];
|
||||
$edit['subject[0][value]'] = 'my comment title';
|
||||
$edit['comment_body[0][value]'] = 'some random comment';
|
||||
$this->drupalGet('comment/reply/node/' . $nodes['comments'][1]->id() . '/comment');
|
||||
$this->drupalPostForm(NULL, $edit, t('Preview'));
|
||||
$this->drupalPostForm(NULL, $edit, t('Save'));
|
||||
|
||||
// Enable counting of statistics.
|
||||
$this->config('statistics.settings')->set('count_content_views', 1)->save();
|
||||
|
||||
// Simulating content views is kind of difficult in the test. Leave that
|
||||
// to the Statistics module. So instead go ahead and manually update the
|
||||
// counter for this node.
|
||||
$nid = $nodes['views'][1]->id();
|
||||
db_insert('node_counter')
|
||||
->fields(['totalcount' => 5, 'daycount' => 5, 'timestamp' => REQUEST_TIME, 'nid' => $nid])
|
||||
->execute();
|
||||
|
||||
// Run cron to update the search index and comment/statistics totals.
|
||||
$this->cronRun();
|
||||
|
||||
// Test that the settings form displays the content ranking section.
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
$this->assertText(t('Content ranking'));
|
||||
|
||||
// Check that all rankings are visible and set to 0.
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
|
||||
}
|
||||
|
||||
// Test each of the possible rankings.
|
||||
$edit = [];
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
// Enable the ranking we are testing.
|
||||
$edit['rankings[' . $node_rank . '][value]'] = 10;
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="10"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 10.');
|
||||
|
||||
// Reload the plugin to get the up-to-date values.
|
||||
$this->nodeSearch = SearchPage::load('node_search');
|
||||
// Do the search and assert the results.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes[$node_rank][1]->id(), 'Search ranking "' . $node_rank . '" order.');
|
||||
|
||||
// Clear this ranking for the next test.
|
||||
$edit['rankings[' . $node_rank . '][value]'] = 0;
|
||||
}
|
||||
|
||||
// Save the final node_rank change then check that all rankings are visible
|
||||
// and have been set back to 0.
|
||||
$this->drupalPostForm('admin/config/search/pages/manage/node_search', $edit, t('Save search page'));
|
||||
$this->drupalGet('admin/config/search/pages/manage/node_search');
|
||||
foreach ($node_ranks as $node_rank) {
|
||||
$this->assertTrue($this->xpath('//select[@id="edit-rankings-' . $node_rank . '-value"]//option[@value="0"]'), 'Select list to prioritize ' . $node_rank . ' for node ranks is visible and set to 0.');
|
||||
}
|
||||
|
||||
// Try with sticky, then promoted. This is a test for issue
|
||||
// https://www.drupal.org/node/771596.
|
||||
$node_ranks = [
|
||||
'sticky' => 10,
|
||||
'promote' => 1,
|
||||
'relevance' => 0,
|
||||
'recent' => 0,
|
||||
'comments' => 0,
|
||||
'views' => 0,
|
||||
];
|
||||
$configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
||||
foreach ($node_ranks as $var => $value) {
|
||||
$configuration['rankings'][$var] = $value;
|
||||
}
|
||||
$this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
||||
$this->nodeSearch->save();
|
||||
|
||||
// Do the search and assert the results. The sticky node should show up
|
||||
// first, then the promoted node, then all the rest.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes['sticky'][1]->id(), 'Search ranking for sticky first worked.');
|
||||
$this->assertEqual($set[1]['node']->id(), $nodes['promote'][1]->id(), 'Search ranking for promoted second worked.');
|
||||
|
||||
// Try with recent, then comments. This is a test for issues
|
||||
// https://www.drupal.org/node/771596 and
|
||||
// https://www.drupal.org/node/303574.
|
||||
$node_ranks = [
|
||||
'sticky' => 0,
|
||||
'promote' => 0,
|
||||
'relevance' => 0,
|
||||
'recent' => 10,
|
||||
'comments' => 1,
|
||||
'views' => 0,
|
||||
];
|
||||
$configuration = $this->nodeSearch->getPlugin()->getConfiguration();
|
||||
foreach ($node_ranks as $var => $value) {
|
||||
$configuration['rankings'][$var] = $value;
|
||||
}
|
||||
$this->nodeSearch->getPlugin()->setConfiguration($configuration);
|
||||
$this->nodeSearch->save();
|
||||
|
||||
// Do the search and assert the results. The recent node should show up
|
||||
// first, then the commented node, then all the rest.
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
$this->assertEqual($set[0]['node']->id(), $nodes['recent'][1]->id(), 'Search ranking for recent first worked.');
|
||||
$this->assertEqual($set[1]['node']->id(), $nodes['comments'][1]->id(), 'Search ranking for comments second worked.');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Test rankings of HTML tags.
|
||||
*/
|
||||
public function testHTMLRankings() {
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Test HTML tags with different weights.
|
||||
$sorted_tags = ['h1', 'h2', 'h3', 'h4', 'a', 'h5', 'h6', 'notag'];
|
||||
$shuffled_tags = $sorted_tags;
|
||||
|
||||
// Shuffle tags to ensure HTML tags are ranked properly.
|
||||
shuffle($shuffled_tags);
|
||||
$settings = [
|
||||
'type' => 'page',
|
||||
'title' => 'Simple node',
|
||||
];
|
||||
$nodes = [];
|
||||
foreach ($shuffled_tags as $tag) {
|
||||
switch ($tag) {
|
||||
case 'a':
|
||||
$settings['body'] = [['value' => \Drupal::l('Drupal Rocks', new Url('<front>')), 'format' => 'full_html']];
|
||||
break;
|
||||
case 'notag':
|
||||
$settings['body'] = [['value' => 'Drupal Rocks']];
|
||||
break;
|
||||
default:
|
||||
$settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
||||
break;
|
||||
}
|
||||
$nodes[$tag] = $this->drupalCreateNode($settings);
|
||||
}
|
||||
|
||||
// Update the search index.
|
||||
$this->nodeSearch->getPlugin()->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
// Do the search and assert the results.
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
|
||||
// Test the ranking of each tag.
|
||||
foreach ($sorted_tags as $tag_rank => $tag) {
|
||||
// Assert the results.
|
||||
if ($tag == 'notag') {
|
||||
$this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for plain text order.');
|
||||
}
|
||||
else {
|
||||
$this->assertEqual($set[$tag_rank]['node']->id(), $nodes[$tag]->id(), 'Search tag ranking for "<' . $sorted_tags[$tag_rank] . '>" order.');
|
||||
}
|
||||
}
|
||||
|
||||
// Test tags with the same weight against the sorted tags.
|
||||
$unsorted_tags = ['u', 'b', 'i', 'strong', 'em'];
|
||||
foreach ($unsorted_tags as $tag) {
|
||||
$settings['body'] = [['value' => "<$tag>Drupal Rocks</$tag>", 'format' => 'full_html']];
|
||||
$node = $this->drupalCreateNode($settings);
|
||||
|
||||
// Update the search index.
|
||||
$this->nodeSearch->getPlugin()->updateIndex();
|
||||
search_update_totals();
|
||||
|
||||
$this->nodeSearch->getPlugin()->setSearch('rocks', [], []);
|
||||
// Do the search and assert the results.
|
||||
$set = $this->nodeSearch->getPlugin()->execute();
|
||||
|
||||
// Ranking should always be second to last.
|
||||
$set = array_slice($set, -2, 1);
|
||||
|
||||
// Assert the results.
|
||||
$this->assertEqual($set[0]['node']->id(), $node->id(), 'Search tag ranking for "<' . $tag . '>" order.');
|
||||
|
||||
// Delete node so it doesn't show up in subsequent search results.
|
||||
$node->delete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\search\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
use Drupal\Component\Utility\SafeMarkup;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
|
||||
/**
|
||||
* Defines the common search test code.
|
||||
|
@ -85,7 +85,7 @@ abstract class SearchTestBase extends WebTestBase {
|
|||
// We have not found a form which contained all fields of $edit and
|
||||
// the submit button.
|
||||
foreach ($edit as $name => $value) {
|
||||
$this->fail(SafeMarkup::format('Failed to set field @name to @value', ['@name' => $name, '@value' => $value]));
|
||||
$this->fail(new FormattableMarkup('Failed to set field @name to @value', ['@name' => $name, '@value' => $value]));
|
||||
}
|
||||
$this->assertTrue($submit_matches, format_string('Found the @submit button', ['@submit' => $submit]));
|
||||
$this->fail(format_string('Found the requested form fields at @path', ['@path' => $path]));
|
||||
|
|
|
@ -74,8 +74,8 @@ class ViewsSearchQuery extends SearchQuery {
|
|||
$conditions =& $condition['field']->conditions();
|
||||
foreach ($conditions as $key => &$subcondition) {
|
||||
if (is_numeric($key)) {
|
||||
// As conditions can have subconditions, for example db_or(), the
|
||||
// function has to be called recursively.
|
||||
// As conditions can be nested, the function has to be called
|
||||
// recursively.
|
||||
$this->conditionReplaceString($search, $replace, $subcondition);
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue