updated core to 7.73

This commit is contained in:
2020-09-24 17:04:08 +02:00
parent 084d28842a
commit 7d87153100
524 changed files with 25194 additions and 7745 deletions
+1 -1
View File
@@ -25,7 +25,7 @@
* the template.
*
* Default keys within $info_split:
* - $info_split['type']: Node type (or item type string supplied by module).
* - $info_split['module']: The module that implemented the search query.
* - $info_split['user']: Author of the node linked to users profile. Depends
* on permission.
* - $info_split['date']: Last update of the node. Short formatted.
+10
View File
@@ -125,6 +125,16 @@ function search_admin_settings($form) {
'#options' => $module_options,
'#description' => t('Choose which search module is the default.')
);
$form['logging'] = array(
'#type' => 'fieldset',
'#title' => t('Logging')
);
$form['logging']['search_logging'] = array(
'#type' => 'checkbox',
'#title' => t('Log searches'),
'#default_value' => variable_get('search_logging', 1),
'#description' => t('If checked, all searches will be logged. Uncheck to skip logging. Logging may affect performance.'),
);
$form['#validate'][] = 'search_admin_settings_validate';
$form['#submit'][] = 'search_admin_settings_submit';
+55 -41
View File
@@ -30,51 +30,26 @@
*
* @return
* Array with optional keys:
* - 'title': Title for the tab on the search page for this module. Defaults
* to the module name if not given.
* - 'path': Path component after 'search/' for searching with this module.
* - title: Title for the tab on the search page for this module. Title must
* be untranslated. Outside of this return array, pass the title through the
* t() function to register it as a translatable string.
* - path: Path component after 'search/' for searching with this module.
* Defaults to the module name if not given.
* - 'conditions_callback': Name of a callback function that is invoked by
* search_view() to get an array of additional search conditions to pass to
* search_data(). For example, a search module may get additional keywords,
* filters, or modifiers for the search from the query string. Sample
* callback function: sample_search_conditions_callback().
* - conditions_callback: An implementation of callback_search_conditions().
*
* @ingroup search
*/
function hook_search_info() {
// Make the title translatable.
t('Content');
return array(
'title' => 'Content',
'path' => 'node',
'conditions_callback' => 'sample_search_conditions_callback',
'conditions_callback' => 'callback_search_conditions',
);
}
/**
* An example conditions callback function for search.
*
* This example pulls additional search keywords out of the $_REQUEST variable,
* (i.e. from the query string of the request). The conditions may also be
* generated internally - for example based on a module's settings.
*
* @see hook_search_info()
* @ingroup search
*/
function sample_search_conditions_callback($keys) {
$conditions = array();
if (!empty($_REQUEST['keys'])) {
$conditions['keys'] = $_REQUEST['keys'];
}
if (!empty($_REQUEST['sample_search_keys'])) {
$conditions['sample_search_keys'] = $_REQUEST['sample_search_keys'];
}
if ($force_keys = variable_get('sample_search_force_keywords', '')) {
$conditions['sample_search_force_keywords'] = $force_keys;
}
return $conditions;
}
/**
* Define access to a custom search routine.
*
@@ -252,22 +227,23 @@ function hook_search_execute($keys = NULL, $conditions = NULL) {
/**
* Override the rendering of search results.
*
* A module that implements hook_search_info() to define a type of search
* may implement this hook in order to override the default theming of
* its search results, which is otherwise themed using theme('search_results').
* A module that implements hook_search_info() to define a type of search may
* implement this hook in order to override the default theming of its search
* results, which is otherwise themed using theme('search_results').
*
* Note that by default, theme('search_results') and theme('search_result')
* work together to create an ordered list (OL). So your hook_search_page()
* implementation should probably do this as well.
*
* @see search-result.tpl.php, search-results.tpl.php
*
* @param $results
* An array of search results.
*
* @return
* A renderable array, which will render the formatted search results with
* a pager included.
* A renderable array, which will render the formatted search results with a
* pager included.
*
* @see search-result.tpl.php
* @see search-results.tpl.php
*/
function hook_search_page($results) {
$output['prefix']['#markup'] = '<ol class="search-results">';
@@ -364,3 +340,41 @@ function hook_update_index() {
/**
* @} End of "addtogroup hooks".
*/
/**
* Provide search query conditions.
*
* Callback for hook_search_info().
*
* This callback is invoked by search_view() to get an array of additional
* search conditions to pass to search_data(). For example, a search module
* may get additional keywords, filters, or modifiers for the search from
* the query string.
*
* This example pulls additional search keywords out of the $_REQUEST variable,
* (i.e. from the query string of the request). The conditions may also be
* generated internally - for example based on a module's settings.
*
* @param $keys
* The search keywords string.
*
* @return
* An array of additional conditions, such as filters.
*
* @ingroup callbacks
* @ingroup search
*/
function callback_search_conditions($keys) {
$conditions = array();
if (!empty($_REQUEST['keys'])) {
$conditions['keys'] = $_REQUEST['keys'];
}
if (!empty($_REQUEST['sample_search_keys'])) {
$conditions['sample_search_keys'] = $_REQUEST['sample_search_keys'];
}
if ($force_keys = config('sample_search.settings')->get('force_keywords')) {
$conditions['sample_search_force_keywords'] = $force_keys;
}
return $conditions;
}
+54 -16
View File
@@ -105,6 +105,8 @@ class SearchQuery extends SelectQueryExtender {
* Stores score expressions.
*
* @var array
*
* @see addScore()
*/
protected $scores = array();
@@ -116,7 +118,7 @@ class SearchQuery extends SelectQueryExtender {
protected $scoresArguments = array();
/**
* Total value of all the multipliers.
* Stores multipliers for score expressions.
*
* @var array
*/
@@ -147,6 +149,17 @@ class SearchQuery extends SelectQueryExtender {
$this->searchExpression = $expression;
$this->type = $module;
// Add a search_* tag. This needs to be added before any preExecute methods
// for decorated queries are called, as $this->prepared will be set to TRUE
// and tags added in the execute method will never get used. For example,
// if $query is extended by 'SearchQuery' then 'PagerDefault', the
// search-specific tag will be added too late (when preExecute() has
// already been called from the PagerDefault extender), and as a
// consequence will not be available to hook_query_alter() implementations,
// nor will the correct hook_query_TAG_alter() implementations get invoked.
// See node_search_execute().
$this->addTag('search_' . $module);
return $this;
}
@@ -206,7 +219,7 @@ class SearchQuery extends SelectQueryExtender {
}
$phrase = FALSE;
// Strip off phrase quotes.
if ($match[2]{0} == '"') {
if ($match[2][0] == '"') {
$match[2] = substr($match[2], 1, -1);
$phrase = TRUE;
$this->simple = FALSE;
@@ -391,21 +404,39 @@ class SearchQuery extends SelectQueryExtender {
/**
* Adds a custom score expression to the search query.
*
* Each score expression can optionally use a multiplier, and multiple
* expressions are combined.
* Score expressions are used to order search results. If no calls to
* addScore() have taken place, a default keyword relevance score will be
* used. However, if at least one call to addScore() has taken place, the
* keyword relevance score is not automatically added.
*
* Note that you must use this method to add ordering to your searches, and
* not call orderBy() directly, when using the SearchQuery extender. This is
* because of the two-pass system the SearchQuery class uses to normalize
* scores.
*
* @param $score
* The score expression.
* The score expression, which should evaluate to a number between 0 and 1.
* The string 'i.relevance' in a score expression will be replaced by a
* measure of keyword relevance between 0 and 1.
* @param $arguments
* Custom query arguments for that expression.
* Query arguments needed to provide values to the score expression.
* @param $multiply
* If set, the score is multiplied with that value. Search query ensures
* that the search scores are still normalized.
* If set, the score is multiplied with this value. However, all scores
* with multipliers are then divided by the total of all multipliers, so
* that overall, the normalization is maintained.
*
* @return object
* The updated query object.
*/
public function addScore($score, $arguments = array(), $multiply = FALSE) {
if ($multiply) {
$i = count($this->multiply);
// Modify the score expression so it is multiplied by the multiplier,
// with a divisor to renormalize.
$score = "CAST(:multiply_$i AS DECIMAL) * COALESCE(( " . $score . "), 0) / CAST(:total_$i AS DECIMAL)";
// Add an argument for the multiplier. The :total_$i argument is taken
// care of in the execute() method, which is when the total divisor is
// calculated.
$arguments[':multiply_' . $i] = $multiply;
$this->multiply[] = $multiply;
}
@@ -446,8 +477,9 @@ class SearchQuery extends SelectQueryExtender {
}
if (count($this->multiply)) {
// Add the total multiplicator as many times as requested to maintain
// normalization as far as possible.
// Re-normalize scores with multipliers by dividing by the total of all
// multipliers. The expressions were altered in addScore(), so here just
// add the arguments for the total.
$i = 0;
$sum = array_sum($this->multiply);
foreach ($this->multiply as $total) {
@@ -456,19 +488,25 @@ class SearchQuery extends SelectQueryExtender {
}
}
// Replace i.relevance pseudo-field with the actual, normalized value.
$this->scores = str_replace('i.relevance', '(' . (1.0 / $this->normalize) . ' * i.score * t.count)', $this->scores);
// Convert scores to an expression.
// Replace the pseudo-expression 'i.relevance' with a measure of keyword
// relevance in all score expressions, using string replacement. Careful
// though! If you just print out a float, some locales use ',' as the
// decimal separator in PHP, while SQL always uses '.'. So, make sure to
// set the number format correctly.
$relevance = number_format((1.0 / $this->normalize), 10, '.', '');
$this->scores = str_replace('i.relevance', '(' . $relevance . ' * i.score * t.count)', $this->scores);
// Add all scores together to form a query field.
$this->addExpression('SUM(' . implode(' + ', $this->scores) . ')', 'calculated_score', $this->scoresArguments);
// If an order has not yet been set for this query, add a default order
// that sorts by the calculated sum of scores.
if (count($this->getOrderBy()) == 0) {
// Add default order after adding the expression.
$this->orderBy('calculated_score', 'DESC');
}
// Add tag and useful metadata.
// Add useful metadata.
$this
->addTag('search_' . $this->type)
->addMetaData('normalize', $this->normalize)
->fields('i', array('type', 'sid'));
+3 -4
View File
@@ -8,8 +8,7 @@ files[] = search.test
configure = admin/config/search/settings
stylesheets[all][] = search.css
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+1
View File
@@ -12,6 +12,7 @@ function search_uninstall() {
variable_del('minimum_word_size');
variable_del('overlap_cjk');
variable_del('search_cron_limit');
variable_del('search_logging');
}
/**
+2 -2
View File
@@ -1067,7 +1067,7 @@ function template_preprocess_search_block_form(&$variables) {
$hidden = array();
// Provide variables named after form keys so themers can print each element independently.
foreach (element_children($variables['form']) as $key) {
$type = $variables['form'][$key]['#type'];
$type = isset($variables['form'][$key]['#type']) ? $variables['form'][$key]['#type'] : '';
if ($type == 'hidden' || $type == 'token') {
$hidden[] = drupal_render($variables['form'][$key]);
}
@@ -1172,7 +1172,7 @@ function search_excerpt($keys, $text) {
}
else {
$info = search_simplify_excerpt_match($key, $text, $included[$key], $boundary);
if ($info['where']) {
if (isset($info['where'])) {
$p = $info['where'];
if ($info['keyword']) {
$foundkeys[] = $info['keyword'];
+5 -4
View File
@@ -49,7 +49,7 @@ function search_view($module = NULL, $keys = '') {
// which will get us back to this page callback. In other words, the search
// form submits with POST but redirects to GET. This way we can keep
// the search query URL clean as a whistle.
if (empty($_POST['form_id']) || $_POST['form_id'] != 'search_form') {
if (empty($_POST['form_id']) || ($_POST['form_id'] != 'search_form' && $_POST['form_id'] != 'search_block_form')) {
$conditions = NULL;
if (isset($info['conditions_callback']) && function_exists($info['conditions_callback'])) {
// Build an optional array of more search conditions.
@@ -57,9 +57,10 @@ function search_view($module = NULL, $keys = '') {
}
// Only search if there are keywords or non-empty conditions.
if ($keys || !empty($conditions)) {
// Log the search keys.
watchdog('search', 'Searched %type for %keys.', array('%keys' => $keys, '%type' => $info['title']), WATCHDOG_NOTICE, l(t('results'), 'search/' . $info['path'] . '/' . $keys));
if (variable_get('search_logging', TRUE)) {
// Log the search keys.
watchdog('search', 'Searched %type for %keys.', array('%keys' => $keys, '%type' => $info['title']), WATCHDOG_NOTICE, l(t('results'), 'search/' . $info['path'] . '/' . $keys));
}
// Collect the search results.
$results = search_data($keys, $info['module'], $conditions);
}
+193 -56
View File
@@ -11,6 +11,9 @@ define('SEARCH_TYPE', '_test_');
define('SEARCH_TYPE_2', '_test2_');
define('SEARCH_TYPE_JPN', '_test3_');
/**
* Indexes content and queries it.
*/
class SearchMatchTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
@@ -275,7 +278,7 @@ class SearchPageText extends DrupalWebTestCase {
$edit = array();
$edit['keys'] = 'bike shed ' . $this->randomName();
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertText(t('Consider loosening your query with OR. bike OR shed will often show more results than bike shed.'), t('Help text is displayed when search returns no results.'));
$this->assertText(t('Consider loosening your query with OR. bike OR shed will often show more results than bike shed.'), 'Help text is displayed when search returns no results.');
$this->assertText(t('Search'));
$this->assertTitle($title, 'Search page title is correct');
@@ -307,6 +310,9 @@ class SearchPageText extends DrupalWebTestCase {
}
}
/**
* Indexes content and tests the advanced search form.
*/
class SearchAdvancedSearchForm extends DrupalWebTestCase {
protected $node;
@@ -342,34 +348,37 @@ class SearchAdvancedSearchForm extends DrupalWebTestCase {
* Test using the advanced search form to limit search to nodes of type "Basic page".
*/
function testNodeType() {
$this->assertTrue($this->node->type == 'page', t('Node type is Basic page.'));
$this->assertTrue($this->node->type == 'page', 'Node type is Basic page.');
// Assert that the dummy title doesn't equal the real title.
$dummy_title = 'Lorem ipsum';
$this->assertNotEqual($dummy_title, $this->node->title, t("Dummy title doesn't equal node title"));
$this->assertNotEqual($dummy_title, $this->node->title, "Dummy title doesn't equal node title");
// Search for the dummy title with a GET query.
$this->drupalGet('search/node/' . $dummy_title);
$this->assertNoText($this->node->title, t('Basic page node is not found with dummy title.'));
$this->assertNoText($this->node->title, 'Basic page node is not found with dummy title.');
// Search for the title of the node with a GET query.
$this->drupalGet('search/node/' . $this->node->title);
$this->assertText($this->node->title, t('Basic page node is found with GET query.'));
$this->assertText($this->node->title, 'Basic page node is found with GET query.');
// Search for the title of the node with a POST query.
$edit = array('or' => $this->node->title);
$this->drupalPost('search/node', $edit, t('Advanced search'));
$this->assertText($this->node->title, t('Basic page node is found with POST query.'));
$this->assertText($this->node->title, 'Basic page node is found with POST query.');
// Advanced search type option.
$this->drupalPost('search/node', array_merge($edit, array('type[page]' => 'page')), t('Advanced search'));
$this->assertText($this->node->title, t('Basic page node is found with POST query and type:page.'));
$this->assertText($this->node->title, 'Basic page node is found with POST query and type:page.');
$this->drupalPost('search/node', array_merge($edit, array('type[article]' => 'article')), t('Advanced search'));
$this->assertText('bike shed', t('Article node is not found with POST query and type:article.'));
$this->assertText('bike shed', 'Article node is not found with POST query and type:article.');
}
}
/**
* Indexes content and tests ranking factors.
*/
class SearchRankingTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
@@ -464,7 +473,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
function testHTMLRankings() {
// Login with sufficient privileges.
$this->drupalLogin($this->drupalCreateUser(array('create page content')));
// Test HTML tags with different weights.
$sorted_tags = array('h1', 'h2', 'h3', 'h4', 'a', 'h5', 'h6', 'notag');
$shuffled_tags = $sorted_tags;
@@ -496,7 +505,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
// Refresh variables after the treatment.
$this->refreshVariables();
// Disable all other rankings.
$node_ranks = array('sticky', 'promote', 'recent', 'comments', 'views');
foreach ($node_ranks as $node_rank) {
@@ -534,7 +543,7 @@ class SearchRankingTestCase extends DrupalWebTestCase {
// Assert the results.
$this->assertEqual($set[0]['node']->nid, $node->nid, 'Search tag ranking for "&lt;' . $tag . '&gt;" order.');
// Delete node so it doesn't show up in subsequent search results.
node_delete($node->nid);
}
@@ -580,6 +589,9 @@ class SearchRankingTestCase extends DrupalWebTestCase {
}
}
/**
* Tests the rendering of the search block.
*/
class SearchBlockTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
@@ -600,13 +612,13 @@ class SearchBlockTestCase extends DrupalWebTestCase {
function testSearchFormBlock() {
// Set block title to confirm that the interface is available.
$this->drupalPost('admin/structure/block/manage/search/form/configure', array('title' => $this->randomName(8)), t('Save block'));
$this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
$this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
// Set the block to a region to confirm block is available.
$edit = array();
$edit['blocks[search_form][region]'] = 'footer';
$this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
$this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
$this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
}
/**
@@ -640,7 +652,7 @@ class SearchBlockTestCase extends DrupalWebTestCase {
$this->assertEqual(
$this->getUrl(),
url('search/node/' . $terms['search_block_form'], array('absolute' => TRUE)),
t('Redirected to correct url.')
'Redirected to correct url.'
);
// Test an empty search via the block form, from the front page.
@@ -652,8 +664,26 @@ class SearchBlockTestCase extends DrupalWebTestCase {
$this->assertEqual(
$this->getUrl(),
url('search/node/', array('absolute' => TRUE)),
t('Redirected to correct url.')
'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.
$terms = array('search_block_form' => 'a');
$this->drupalPost('node', $terms, t('Search'));
$this->assertText('You must include at least one positive keyword with 3 characters or more');
$terms = array('search_block_form' => 'foo');
$this->drupalPost(NULL, $terms, t('Search'));
$this->assertNoText('You must include at least one positive keyword with 3 characters or more');
$this->assertText('Your search yielded no results');
// Same test again, using the search page form for the second search this time.
$terms = array('search_block_form' => 'a');
$this->drupalPost('node', $terms, t('Search'));
$terms = array('keys' => 'foo');
$this->drupalPost(NULL, $terms, t('Search'));
$this->assertNoText('You must include at least one positive keyword with 3 characters or more');
$this->assertText('Your search yielded no results');
}
}
@@ -727,7 +757,7 @@ class SearchCommentTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Comment Search tests',
'description' => 'Verify text formats and filters used elsewhere.',
'description' => 'Test integration searching comments.',
'group' => 'Search',
);
}
@@ -790,20 +820,20 @@ class SearchCommentTestCase extends DrupalWebTestCase {
'search_block_form' => "'" . $edit_comment['subject'] . "'",
);
$this->drupalPost('', $edit, t('Search'));
$this->assertText($node->title, t('Node found in search results.'));
$this->assertText($edit_comment['subject'], t('Comment subject found in search results.'));
$this->assertText($node->title, 'Node found in search results.');
$this->assertText($edit_comment['subject'], 'Comment subject found in search results.');
// Search for the comment body.
$edit = array(
'search_block_form' => "'" . $comment_body . "'",
);
$this->drupalPost('', $edit, t('Search'));
$this->assertText($node->title, t('Node found in search results.'));
$this->assertText($node->title, 'Node found in search results.');
// Verify that comment is rendered using proper format.
$this->assertText($comment_body, t('Comment body text found in search results.'));
$this->assertNoRaw(t('n/a'), t('HTML in comment body is not hidden.'));
$this->assertNoRaw(check_plain($edit_comment['comment_body[' . LANGUAGE_NONE . '][0][value]']), t('HTML in comment body is not escaped.'));
$this->assertText($comment_body, 'Comment body text found in search results.');
$this->assertNoRaw(t('n/a'), 'HTML in comment body is not hidden.');
$this->assertNoRaw(check_plain($edit_comment['comment_body[' . LANGUAGE_NONE . '][0][value]']), 'HTML in comment body is not escaped.');
// Hide comments.
$this->drupalLogin($this->admin_user);
@@ -816,7 +846,7 @@ class SearchCommentTestCase extends DrupalWebTestCase {
// Search for $title.
$this->drupalPost('', $edit, t('Search'));
$this->assertNoText($comment_body, t('Comment body text not found in search results.'));
$this->assertNoText($comment_body, 'Comment body text not found in search results.');
}
/**
@@ -875,7 +905,7 @@ class SearchCommentTestCase extends DrupalWebTestCase {
$this->setRolePermissions(DRUPAL_AUTHENTICATED_RID, TRUE, TRUE);
$this->setRolePermissions($this->admin_role, TRUE, FALSE);
$this->checkCommentAccess('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', TRUE);
}
/**
@@ -926,7 +956,7 @@ class SearchCommentTestCase extends DrupalWebTestCase {
// Verify that if you view the node on its own page, 'add new comment'
// is there.
$this->drupalGet('node/' . $node->nid);
$this->assertText(t('Add new comment'), t('Add new comment appears on node page'));
$this->assertText(t('Add new comment'), 'Add new comment appears on node page');
// Run cron to index this page.
$this->drupalLogout();
@@ -935,13 +965,13 @@ class SearchCommentTestCase extends DrupalWebTestCase {
// Search for 'comment'. Should be no results.
$this->drupalLogin($user);
$this->drupalPost('search/node', array('keys' => 'comment'), t('Search'));
$this->assertText(t('Your search yielded no results'), t('No results searching for the word comment'));
$this->assertText(t('Your search yielded no results'), 'No results searching for the word comment');
// Search for the node title. Should be found, and 'Add new comment' should
// not be part of the search snippet.
$this->drupalPost('search/node', array('keys' => 'short'), t('Search'));
$this->assertText($node->title, t('Search for keyword worked'));
$this->assertNoText(t('Add new comment'), t('Add new comment does not appear on search results page'));
$this->assertText($node->title, 'Search for keyword worked');
$this->assertNoText(t('Add new comment'), 'Add new comment does not appear on search results page');
}
}
@@ -1074,8 +1104,8 @@ class SearchCommentCountToggleTestCase extends DrupalWebTestCase {
// Test comment count display for nodes with comment status set to Open
$this->drupalPost('', $edit, t('Search'));
$this->assertText(t('0 comments'), t('Empty comment count displays for nodes with comment status set to Open'));
$this->assertText(t('1 comment'), t('Non-empty comment count displays for nodes with comment status set to Open'));
$this->assertText(t('0 comments'), 'Empty comment count displays for nodes with comment status set to Open');
$this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Open');
// Test comment count display for nodes with comment status set to Closed
$this->searchable_nodes['0 comments']->comment = COMMENT_NODE_CLOSED;
@@ -1084,8 +1114,8 @@ class SearchCommentCountToggleTestCase extends DrupalWebTestCase {
node_save($this->searchable_nodes['1 comment']);
$this->drupalPost('', $edit, t('Search'));
$this->assertNoText(t('0 comments'), t('Empty comment count does not display for nodes with comment status set to Closed'));
$this->assertText(t('1 comment'), t('Non-empty comment count displays for nodes with comment status set to Closed'));
$this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Closed');
$this->assertText(t('1 comment'), 'Non-empty comment count displays for nodes with comment status set to Closed');
// Test comment count display for nodes with comment status set to Hidden
$this->searchable_nodes['0 comments']->comment = COMMENT_NODE_HIDDEN;
@@ -1094,8 +1124,8 @@ class SearchCommentCountToggleTestCase extends DrupalWebTestCase {
node_save($this->searchable_nodes['1 comment']);
$this->drupalPost('', $edit, t('Search'));
$this->assertNoText(t('0 comments'), t('Empty comment count does not display for nodes with comment status set to Hidden'));
$this->assertNoText(t('1 comment'), t('Non-empty comment count does not display for nodes with comment status set to Hidden'));
$this->assertNoText(t('0 comments'), 'Empty comment count does not display for nodes with comment status set to Hidden');
$this->assertNoText(t('1 comment'), 'Non-empty comment count does not display for nodes with comment status set to Hidden');
}
}
@@ -1160,7 +1190,7 @@ class SearchSimplifyTestCase extends DrupalWebTestCase {
for ($i = 0; $i < 32; $i++) {
$string .= chr($i);
}
$this->assertIdentical(' ', search_simplify($string), t('Search simplify works for ASCII control characters.'));
$this->assertIdentical(' ', search_simplify($string), 'Search simplify works for ASCII control characters.');
}
/**
@@ -1316,7 +1346,7 @@ class SearchNumbersTestCase extends DrupalWebTestCase {
$this->drupalPost('search/node',
array('keys' => $number),
t('Search'));
$this->assertText($node->title, $type . ': node title shown (search found the node) in search for number ' . $number);
$this->assertText($node->title, format_string('%type: node title shown (search found the node) in search for number %number.', array('%type' => $type, '%number' => $number)));
}
}
}
@@ -1384,7 +1414,7 @@ class SearchNumberMatchingTestCase extends DrupalWebTestCase {
$this->drupalPost('search/node',
array('keys' => 'foo'),
t('Search'));
$this->assertNoText($node->title, $i . ': node title not shown in dummy search');
$this->assertNoText($node->title, format_string('%number: node title not shown in dummy search', array('%number' => $i)));
// Now verify that we can find node i by searching for any of the
// numbers.
@@ -1397,7 +1427,7 @@ class SearchNumberMatchingTestCase extends DrupalWebTestCase {
$this->drupalPost('search/node',
array('keys' => $number),
t('Search'));
$this->assertText($node->title, $i . ': node title shown (search found the node) in search for number ' . $number);
$this->assertText($node->title, format_string('%i: node title shown (search found the node) in search for number %number', array('%i' => $i, '%number' => $number)));
}
}
@@ -1423,7 +1453,7 @@ class SearchConfigSettingsForm extends DrupalWebTestCase {
parent::setUp('search', 'search_extra_type');
// Login as a user that can create and search content.
$this->search_user = $this->drupalCreateUser(array('search content', 'administer search', 'administer nodes', 'bypass node access', 'access user profiles', 'administer users', 'administer blocks'));
$this->search_user = $this->drupalCreateUser(array('search content', 'administer search', 'administer nodes', 'bypass node access', 'access user profiles', 'administer users', 'administer blocks', 'access site reports'));
$this->drupalLogin($this->search_user);
// Add a single piece of content and index it.
@@ -1472,6 +1502,19 @@ class SearchConfigSettingsForm extends DrupalWebTestCase {
);
$this->drupalPost('admin/config/search/settings', $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 on by default.
$text = $this->randomName(5);
$this->drupalPost('search/node', array('keys' => $text), t('Search'));
$this->drupalGet('admin/reports/dblog');
$this->assertLink('Searched Content for ' . $text . '.', 0, 'Search was logged');
// Turn off logging.
variable_set('search_logging', FALSE);
$text = $this->randomName(5);
$this->drupalPost('search/node', array('keys' => $text), t('Search'));
$this->drupalGet('admin/reports/dblog');
$this->assertNoLink('Searched Content for ' . $text . '.', 'Search was not logged');
}
/**
@@ -1558,7 +1601,7 @@ class SearchConfigSettingsForm extends DrupalWebTestCase {
$this->drupalGet($path);
foreach ($modules as $module) {
$title = $module_info[$module]['title'];
$this->assertText($title, $title . ' search tab is shown');
$this->assertText($title, format_string('%title search tab is shown', array('%title' => $title)));
}
}
}
@@ -1567,7 +1610,7 @@ class SearchConfigSettingsForm extends DrupalWebTestCase {
/**
* Tests the search_excerpt() function.
*/
class SearchExcerptTestCase extends DrupalUnitTestCase {
class SearchExcerptTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Search excerpt extraction',
@@ -1577,8 +1620,7 @@ class SearchExcerptTestCase extends DrupalUnitTestCase {
}
function setUp() {
drupal_load('module', 'search');
parent::setUp();
parent::setUp('search');
}
/**
@@ -1603,7 +1645,7 @@ class SearchExcerptTestCase extends DrupalUnitTestCase {
$this->assertEqual($result, 'The quick brown <strong>fox</strong> &amp; jumps over the lazy dog ...', 'Found keyword is highlighted');
$longtext = str_repeat($text . ' ', 10);
$result = preg_replace('| +|', ' ', search_excerpt('nothing', $text));
$result = preg_replace('| +|', ' ', search_excerpt('nothing', $longtext));
$this->assertTrue(strpos($result, $expected) === 0, 'When keyword is not found in long string, return value starts as expected');
$entities = str_repeat('k&eacute;sz&iacute;t&eacute;se ', 20);
@@ -1955,42 +1997,42 @@ class SearchLanguageTestCase extends DrupalWebTestCase {
function testLanguages() {
// Check that there are initially no languages displayed.
$this->drupalGet('search/node');
$this->assertNoText(t('Languages'), t('No languages to choose from.'));
$this->assertNoText(t('Languages'), 'No languages to choose from.');
// Add predefined language.
$edit = array('langcode' => 'fr');
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
$this->assertText('fr', t('Language added successfully.'));
$this->assertText('fr', 'Language added successfully.');
// Now we should have languages displayed.
$this->drupalGet('search/node');
$this->assertText(t('Languages'), t('Languages displayed to choose from.'));
$this->assertText(t('English'), t('English is a possible choice.'));
$this->assertText(t('French'), t('French is a possible choice.'));
$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->drupalPost('search/node', array(), t('Advanced search'));
$this->assertEqual($this->getUrl(), url('search/node/', array('absolute' => TRUE)), t('Correct page redirection, no language filtering.'));
$this->assertEqual($this->getUrl(), url('search/node/', array('absolute' => TRUE)), 'Correct page redirection, no language filtering.');
// Pick French and ensure it is selected.
$edit = array('language[fr]' => TRUE);
$this->drupalPost('search/node', $edit, t('Advanced search'));
$this->assertFieldByXPath('//input[@name="keys"]', 'language:fr', t('Language filter added to query.'));
$this->assertFieldByXPath('//input[@name="keys"]', 'language:fr', 'Language filter added to query.');
// Change the default language and disable English.
$path = 'admin/config/regional/language';
$this->drupalGet($path);
$this->assertFieldChecked('edit-site-default-en', t('English is the default language.'));
$this->assertFieldChecked('edit-site-default-en', 'English is the default language.');
$edit = array('site_default' => 'fr');
$this->drupalPost(NULL, $edit, t('Save configuration'));
$this->assertNoFieldChecked('edit-site-default-en', t('Default language updated.'));
$this->assertNoFieldChecked('edit-site-default-en', 'Default language updated.');
$edit = array('enabled[en]' => FALSE);
$this->drupalPost('admin/config/regional/language', $edit, t('Save configuration'));
$this->assertNoFieldChecked('edit-enabled-en', t('Language disabled.'));
$this->assertNoFieldChecked('edit-enabled-en', 'Language disabled.');
// Check that there are again no languages displayed.
$this->drupalGet('search/node');
$this->assertNoText(t('Languages'), t('No languages to choose from.'));
$this->assertNoText(t('Languages'), 'No languages to choose from.');
}
}
@@ -2018,10 +2060,11 @@ class SearchNodeAccessTest extends DrupalWebTestCase {
}
/**
* Tests that search returns results with punctuation in the search phrase.
* Tests that search works with punctuation and HTML entities.
*/
function testPhraseSearchPunctuation() {
$node = $this->drupalCreateNode(array('body' => array(LANGUAGE_NONE => array(array('value' => "The bunny's ears were fuzzy.")))));
$node2 = $this->drupalCreateNode(array('body' => array(LANGUAGE_NONE => array(array('value' => 'Dignissim Aliquam &amp; Quieligo meus natu quae quia te. Damnum&copy; erat&mdash; neo pneum. Facilisi feugiat ibidem ratis.')))));
// Update the search index.
module_invoke_all('update_index');
@@ -2034,5 +2077,99 @@ class SearchNodeAccessTest extends DrupalWebTestCase {
$edit = array('keys' => '"bunny\'s"');
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertText($node->title);
// Search for "&" and verify entities are not broken up in the output.
$edit = array('keys' => '&');
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertNoRaw('<strong>&</strong>amp;');
$this->assertText('You must include at least one positive keyword');
$edit = array('keys' => '&amp;');
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertNoRaw('<strong>&</strong>amp;');
$this->assertText('You must include at least one positive keyword');
}
}
/**
* Tests node search with query tags.
*/
class SearchNodeTagTest extends DrupalWebTestCase {
public $test_user;
public static function getInfo() {
return array(
'name' => 'Node search query tags',
'description' => 'Tests Node search tags functionality.',
'group' => 'Search',
);
}
function setUp() {
parent::setUp('search', 'search_node_tags');
node_access_rebuild();
// Create a test user and log in.
$this->test_user = $this->drupalCreateUser(array('search content'));
$this->drupalLogin($this->test_user);
}
/**
* Tests that the correct tags are available and hooks invoked.
*/
function testNodeSearchQueryTags() {
$this->drupalCreateNode(array('body' => array(LANGUAGE_NONE => array(array('value' => 'testing testing testing.')))));
// Update the search index.
module_invoke_all('update_index');
search_update_totals();
$edit = array('keys' => 'testing');
$this->drupalPost('search/node', $edit, t('Search'));
$this->assertTrue(variable_get('search_node_tags_test_query_tag', FALSE), 'hook_query_alter() was invoked and the query contained the "search_node" tag.');
$this->assertTrue(variable_get('search_node_tags_test_query_tag_hook', FALSE), 'hook_query_search_node_alter() was invoked.');
}
}
/**
* Tests searching with locale values set.
*/
class SearchSetLocaleTest extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => 'Search with numeric locale set',
'description' => 'Check that search works with numeric locale settings',
'group' => 'Search',
);
}
function setUp() {
parent::setUp('search');
// Create a simple node so something will be put in the index.
$info = array(
'body' => array(LANGUAGE_NONE => array(array('value' => 'Tapir'))),
);
$this->drupalCreateNode($info);
// Run cron to index.
$this->cronRun();
}
/**
* Verify that search works with a numeric locale set.
*/
public function testSearchWithNumericLocale() {
// French decimal point is comma.
setlocale(LC_NUMERIC, 'fr_FR');
// An exception will be thrown if a float in the wrong format occurs in the
// query to the database, so an assertion is not necessary here.
db_select('search_index', 'i')
->extend('searchquery')
->searchexpression('tapir', 'node')
->execute();
}
}
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
+3 -4
View File
@@ -5,8 +5,7 @@ version = VERSION
core = 7.x
hidden = TRUE
; Information added by drupal.org packaging script on 2013-04-03
version = "7.22"
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1365027012"
datestamp = "1600272641"
@@ -0,0 +1,11 @@
name = "Test search node tags"
description = "Support module for Node search tags testing."
package = Testing
version = VERSION
core = 7.x
hidden = TRUE
; Information added by Drupal.org packaging script on 2020-09-16
version = "7.73"
project = "drupal"
datestamp = "1600272641"
@@ -0,0 +1,23 @@
<?php
/**
* @file
* Dummy module implementing a node search hooks for search module testing.
*/
/**
* Implements hook_query_alter().
*/
function search_node_tags_query_alter(QueryAlterableInterface $query) {
if ($query->hasTag('search_node')) {
variable_set('search_node_tags_test_query_tag', TRUE);
}
}
/**
* Implements hook_query_TAG_alter().
*/
function search_node_tags_query_search_node_alter(QueryAlterableInterface $query) {
variable_set('search_node_tags_test_query_tag_hook', TRUE);
}