function search_parse_query in Drupal 5
Same name and namespace in other branches
- 4 modules/search.module \search_parse_query()
- 6 modules/search/search.module \search_parse_query()
Parse a search query into SQL conditions.
We build a query that matches the dataset bodies.
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 642 - 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;
foreach ($matches as $match) {
$phrase = FALSE;
// Strip off phrase quotes
if ($match[2][0] == '"') {
$match[2] = substr($match[2], 1, -1);
$phrase = TRUE;
}
// 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;
}
else {
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;
// Positive matches
foreach ($keys['positive'] as $key) {
// Group of ORed terms
if (is_array($key) && count($key)) {
$queryor = array();
$any = FALSE;
foreach ($key as $or) {
list($q, $count) = _search_parse_query($or, $arguments2);
$any |= $count;
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 {
list($q, $count) = _search_parse_query($key, $arguments2);
if ($q) {
$query[] = $q;
$arguments[] = $key;
// Each AND keyword needs to match at least once
$matches += $count;
}
}
}
// Negative matches
foreach ($keys['negative'] as $key) {
list($q) = _search_parse_query($key, $arguments2, TRUE);
if ($q) {
$query[] = $q;
$arguments[] = $key;
}
}
$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,
);
}