Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.257
diff -u -u -p -r1.257 search.module
--- modules/search/search.module 14 May 2008 15:07:25 -0000 1.257
+++ modules/search/search.module 17 May 2008 02:58:07 -0000
@@ -770,10 +770,10 @@ function search_parse_query($text) {
}
// Convert keywords into SQL statements.
- $query = array();
- $query2 = array();
- $arguments = array();
- $arguments2 = array();
+ $phrase_query = array();
+ $keyword_query = array();
+ $phrase_arguments = array();
+ $keyword_arguments = array();
$matches = 0;
$simple_and = FALSE;
$simple_or = FALSE;
@@ -785,15 +785,15 @@ function search_parse_query($text) {
$queryor = array();
$any = FALSE;
foreach ($key as $or) {
- list($q, $num_new_scores) = _search_parse_query($or, $arguments2);
+ list($q, $num_new_scores) = _search_parse_query($or, $keyword_arguments);
$any |= $num_new_scores;
if ($q) {
$queryor[] = $q;
- $arguments[] = $or;
+ $phrase_arguments[] = $or;
}
}
if (count($queryor)) {
- $query[] = '(' . implode(' OR ', $queryor) . ')';
+ $phrase_query[] = '(' . implode(' OR ', $queryor) . ')';
// A group of OR keywords only needs to match once
$matches += ($any > 0);
}
@@ -801,10 +801,10 @@ function search_parse_query($text) {
// Single ANDed term
else {
$simple_and = TRUE;
- list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $arguments2);
+ list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $keyword_arguments);
if ($q) {
- $query[] = $q;
- $arguments[] = $key;
+ $phrase_query[] = $q;
+ $phrase_arguments[] = $key;
if (!$num_valid_words) {
$simple = FALSE;
}
@@ -818,19 +818,19 @@ function search_parse_query($text) {
}
// Negative matches
foreach ($keys['negative'] as $key) {
- list($q) = _search_parse_query($key, $arguments2, TRUE);
+ list($q) = _search_parse_query($key, $keyword_arguments, TRUE);
if ($q) {
- $query[] = $q;
- $arguments[] = $key;
+ $phrase_query[] = $q;
+ $phrase_arguments[] = $key;
$simple = FALSE;
}
}
- $query = implode(' AND ', $query);
+ $phrase_query = implode(' AND ', $phrase_query);
// Build word-index conditions for the first pass
- $query2 = substr(str_repeat("i.word = '%s' OR ", count($arguments2)), 0, -4);
+ $keyword_query = substr(str_repeat("i.word = '%s' OR ", count($keyword_arguments)), 0, -4);
- return array($query, $arguments, $query2, $arguments2, $matches, $simple, $warning);
+ return compact('phrase_query', 'phrase_arguments', 'keyword_query', 'keyword_arguments', 'matches', 'simple', 'warning');
}
/**
@@ -915,44 +915,70 @@ function _search_parse_query(&$word, &$s
function do_search($keywords, $type, $join1 = '', $where1 = '1', $arguments1 = array(), $columns2 = 'i.relevance AS score', $join2 = '', $arguments2 = array(), $sort_parameters = 'ORDER BY score DESC') {
$query = search_parse_query($keywords);
- if ($query[2] == '') {
- form_set_error('keys', t('You must include at least one positive keyword with @count characters or more.', array('@count' => variable_get('minimum_word_size', 3))));
- }
- if ($query[6]) {
- if ($query[6] == 'or') {
- drupal_set_message(t('Search for either of the two terms with uppercase OR. For example, cats OR dogs.'));
- }
+ // If nothing is being searched for, get out of here.
+ if ($query['phrase_query'] == '' || $query['keyword_query'] == '') {
+ return array();
}
- if ($query === NULL || $query[0] == '' || $query[2] == '') {
+
+ // Calculate maximum keyword relevance, to normalize it.
+ // Start with a COUNT query.
+ $count_arguments = array();
+ $count_joins = array($join1);
+ $count_wheres = array($where1);
+
+ if ($query['keyword_query']) {
+ $count_wheres[] = "($query[keyword_query])";
+ $count_arguments = array_merge($count_arguments, $query['keyword_arguments']);
+ }
+ $count_wheres[] = "i.type = '%s'";
+ $count_arguments[] = $type;
+ if (!$query['simple']) {
+ // Complex queries have a JOIN and WHERE for phrases plus extra arguments.
+ $count_joins[] = 'INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type';
+ $count_arguments = array_merge($count_arguments, $query['phrase_arguments']);
+ $count_wheres[] = "($query[phrase_query])";
+ }
+ $count_arguments[] = $query['matches'];
+
+ $count_join = implode(' ', $count_joins);
+ $count_where = implode(' AND ', $count_wheres);
+
+ // Execute the count query before the main query.
+ $count = db_result(db_query("SELECT COUNT(*) FROM (SELECT 1 FROM {search_index} i $count_join WHERE $count_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d) n1", $count_arguments));
+ // If there aren't any results, return empty.
+ if ($count == 0) {
return array();
}
+ // Build the simplest of all queries for db_pager().
+ $count_select = "SELECT $count";
// Build query for keyword normalization.
- $conditions = "$where1 AND ($query[2]) AND i.type = '%s'";
- $arguments1 = array_merge($arguments1, $query[3], array($type));
- $join = "INNER JOIN {search_total} t ON i.word = t.word $join1";
- if (!$query[5]) {
- $conditions .= " AND ($query[0])";
- $arguments1 = array_merge($arguments1, $query[1]);
- $join .= " INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type";
- }
-
- // Calculate maximum keyword relevance, to normalize it.
- $select = "SELECT SUM(i.score * t.count) AS score FROM {search_index} i $join WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY score DESC";
- $arguments = array_merge($arguments1, array($query[4]));
- $normalize = db_result(db_query_range($select, $arguments, 0, 1));
+ $query_arguments = array_merge($arguments1, $query['keyword_arguments'], array($type));
+ $query_joins = array("INNER JOIN {search_total} t ON i.word = t.word", $join1);
+ $query_wheres = array($where1, "($query[keyword_query])", "i.type = '%s'");
+
+ if (!$query['simple']) {
+ $query_wheres[] = "($query[phrase_query])";
+ $query_arguments = array_merge($query_arguments, $query['phrase_arguments']);
+ $query_joins[] = "INNER JOIN {search_dataset} d ON i.sid = d.sid AND i.type = d.type";
+ }
+
+ $query_arguments[] = $query['matches'];
+ $query_join = implode(' ', $query_joins);
+ $query_where = implode(' AND ', $query_wheres);
+
+ $select = "SELECT SUM(i.score * t.count) AS score FROM {search_index} i $query_join WHERE $query_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d ORDER BY score DESC";
+ $normalize = db_result(db_query_range($select, $query_arguments, 0, 1));
if (!$normalize) {
return array();
}
- $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * SUM(i.score * t.count))', $columns2);
// Build query to retrieve results.
- $select = "SELECT i.type, i.sid, $columns2 FROM {search_index} i $join $join2 WHERE $conditions GROUP BY i.type, i.sid HAVING COUNT(*) >= %d";
- $count_select = "SELECT COUNT(*) FROM ($select) n1";
- $arguments = array_merge($arguments2, $arguments1, array($query[4]));
-
+ $columns2 = str_replace('i.relevance', '(' . (1.0 / $normalize) . ' * SUM(i.score * t.count))', $columns2);
+ $select = "SELECT i.type, i.sid, $columns2 FROM {search_index} i $query_join $join2 WHERE $query_where GROUP BY i.type, i.sid HAVING COUNT(*) >= %d";
+
// Do actual search query
- $result = pager_query("$select $sort_parameters", 10, 0, $count_select, $arguments);
+ $result = pager_query("$select $sort_parameters", 10, 0, $count_select, array_merge($arguments2, $query_arguments));
$results = array();
while ($item = db_fetch_object($result)) {
$results[] = $item;
@@ -1068,9 +1094,9 @@ function search_box(&$form_state, $form_
'#attributes' => array('title' => t('Enter the terms you wish to search for.')),
);
$form['submit'] = array('#type' => 'submit', '#value' => t('Search'));
+ $form['#validate'][] = 'search_form_validate';
$form['#submit'][] = 'search_box_form_submit';
- $form['#validate'][] = 'search_box_form_validate';
-
+ $form['#submit'][] = 'search_form_submit';
return $form;
}
@@ -1079,7 +1105,8 @@ function search_box(&$form_state, $form_
*/
function search_box_form_submit($form, &$form_state) {
$form_id = $form['form_id']['#value'];
- $form_state['redirect'] = 'search/node/' . trim($form_state['values'][$form_id]);
+ $form_state['values']['processed_keys'] = trim($form_state['values'][$form_id]);
+ $form_state['values']['module'] = 'node';
}
/**
Index: modules/search/search.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.pages.inc,v
retrieving revision 1.5
diff -u -u -p -r1.5 search.pages.inc
--- modules/search/search.pages.inc 14 Apr 2008 17:48:41 -0000 1.5
+++ modules/search/search.pages.inc 17 May 2008 02:58:07 -0000
@@ -124,6 +124,17 @@ function search_form_submit($form, &$for
// Fall through to the drupal_goto() call.
}
+ $query = search_parse_query($keys);
+ if ($query['keyword_query'] == '') {
+ form_set_error('keys', t('You must include at least one positive keyword with @count characters or more.', array('@count' => variable_get('minimum_word_size', 3))));
+ }
+
+ // Warn users if they have the word 'or' in their query that only uppercase
+ // OR is recognized as a boolean modifier.
+ if ($query['warning'] == 'or') {
+ drupal_set_message(t('Search for either of the two terms with uppercase OR. For example, cats OR dogs.'));
+ }
+
$type = $form_state['values']['module'] ? $form_state['values']['module'] : 'node';
$form_state['redirect'] = 'search/' . $type . '/' . $keys;
return;
Index: modules/system/system.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.admin.inc,v
retrieving revision 1.76
diff -u -u -p -r1.76 system.admin.inc
--- modules/system/system.admin.inc 10 May 2008 07:32:02 -0000 1.76
+++ modules/system/system.admin.inc 17 May 2008 02:58:07 -0000
@@ -2263,4 +2263,4 @@ function theme_system_themes_form($form)
$output = theme('table', $header, $rows);
$output .= drupal_render($form);
return $output;
-}
\ No newline at end of file
+}