function search_parse_query in Drupal 6
Same name and namespace in other branches
- 4 modules/search.module \search_parse_query()
- 5 modules/search/search.module \search_parse_query()
Parse a search query into SQL conditions.
We build two queries that matches the dataset bodies. @See do_search for more about these.
Parameters
$text: The search keys.
Return value
A list of six elements.
- A series of statements AND'd together which will be used to provide all possible matches.
- Arguments for this query part.
- A series of exact word matches OR'd together.
- Arguments for this query part.
- A bool indicating whether this is a simple query or not. Negative terms, presence of both AND / OR make this FALSE.
- A bool indicating the presence of a lowercase or. Maybe the user wanted to use OR.
1 call to search_parse_query()
- do_search in modules/
search/ search.module - Do a query on the full-text search index for a word or words.
File
- modules/
search/ search.module, line 710 - Enables site-wide keyword searching.
Code
function search_parse_query($text) {
$keys = array(
'positive' => array(),
'negative' => array(),
);
// Tokenize query string
preg_match_all('/ (-?)("[^"]+"|[^" ]+)/i', ' ' . $text, $matches, PREG_SET_ORDER);
if (count($matches) < 1) {
return NULL;
}
// Classify tokens
$or = FALSE;
$warning = '';
$simple = TRUE;
foreach ($matches as $match) {
$phrase = FALSE;
// Strip off phrase quotes
if ($match[2][0] == '"') {
$match[2] = substr($match[2], 1, -1);
$phrase = TRUE;
$simple = FALSE;
}
// Simplify keyword according to indexing rules and external preprocessors
$words = search_simplify($match[2]);
// Re-explode in case simplification added more words, except when matching a phrase
$words = $phrase ? array(
$words,
) : preg_split('/ /', $words, -1, PREG_SPLIT_NO_EMPTY);
// Negative matches
if ($match[1] == '-') {
$keys['negative'] = array_merge($keys['negative'], $words);
}
elseif ($match[2] == 'OR' && count($keys['positive'])) {
$last = array_pop($keys['positive']);
// Starting a new OR?
if (!is_array($last)) {
$last = array(
$last,
);
}
$keys['positive'][] = $last;
$or = TRUE;
continue;
}
elseif ($match[2] == 'AND' || $match[2] == 'and') {
$warning = $match[2];
continue;
}
else {
if ($match[2] == 'or') {
$warning = $match[2];
}
if ($or) {
// Add to last element (which is an array)
$keys['positive'][count($keys['positive']) - 1] = array_merge($keys['positive'][count($keys['positive']) - 1], $words);
}
else {
$keys['positive'] = array_merge($keys['positive'], $words);
}
}
$or = FALSE;
}
// Convert keywords into SQL statements.
$query = array();
$query2 = array();
$arguments = array();
$arguments2 = array();
$matches = 0;
$simple_and = FALSE;
$simple_or = FALSE;
// Positive matches
foreach ($keys['positive'] as $key) {
// Group of ORed terms
if (is_array($key) && count($key)) {
$simple_or = TRUE;
$queryor = array();
$any = FALSE;
foreach ($key as $or) {
list($q, $num_new_scores) = _search_parse_query($or, $arguments2);
$any |= $num_new_scores;
if ($q) {
$queryor[] = $q;
$arguments[] = $or;
}
}
if (count($queryor)) {
$query[] = '(' . implode(' OR ', $queryor) . ')';
// A group of OR keywords only needs to match once
$matches += $any > 0;
}
}
else {
$simple_and = TRUE;
list($q, $num_new_scores, $num_valid_words) = _search_parse_query($key, $arguments2);
if ($q) {
$query[] = $q;
$arguments[] = $key;
if (!$num_valid_words) {
$simple = FALSE;
}
// Each AND keyword needs to match at least once
$matches += $num_new_scores;
}
}
}
if ($simple_and && $simple_or) {
$simple = FALSE;
}
// Negative matches
foreach ($keys['negative'] as $key) {
list($q) = _search_parse_query($key, $arguments2, TRUE);
if ($q) {
$query[] = $q;
$arguments[] = $key;
$simple = FALSE;
}
}
$query = implode(' AND ', $query);
// Build word-index conditions for the first pass
$query2 = substr(str_repeat("i.word = '%s' OR ", count($arguments2)), 0, -4);
return array(
$query,
$arguments,
$query2,
$arguments2,
$matches,
$simple,
$warning,
);
}