/** * Process the filters for the query string * * @param vB_Legacy_Current_User $user user requesting the search * @param vB_Search_Criteria $criteria search criteria to process */ protected function process_keywords_filters(vB_Search_Criteria &$criteria) { $keywords = $criteria->get_keywords(); // nothing to process if (empty($keywords)) { return; } $words = array(); // get the map table names for the keywords. these tables will be joined into the search query $has_or_joiner = false; foreach ($keywords as $word_details) { $suffix = vBDBSearch_Core::get_table_name($word_details['word']); //$words[$suffix][$clean_word] = array('wordid'=>false,'joiner'=>$word['joiner']); $words[$word_details['word']] = array('suffix' => $suffix, 'word' => $word_details['word'], 'joiner' => $word_details['joiner']); if ($word_details['joiner'] == "OR") { $has_or_joiner = true; } } // nothing to process if (empty($words)) { return; } $set = $this->db->query_read_slave($query = "\n\t\t\t\t\tSELECT *\n\t\t\t\t\tFROM " . TABLE_PREFIX . "words as words\n\t\t\t\t\tWHERE " . self::make_equals_filter('words', 'word', array_keys($words))); $config = vB::getConfig(); if (!empty($config['Misc']['debug_sql']) or self::DEBUG) { echo "{$query};\n"; } $wordids = array(); while ($word_details = $this->db->fetch_array($set)) { $wordids[$word_details['word']] = $word_details['wordid']; } $this->db->free_result($set); $word_details = array(); foreach ($words as $word => $details) { // if the word was not found if (!isset($wordids[$word])) { // and it's not with a NOT or OR operator if (!$has_or_joiner and $details['joiner'] != 'NOT') { // this word is not indexed so there is nothing to return $this->where[] = "0 /** word is not indexed **/"; $this->sort = array('node.created' => 'ASC'); return; } // still need to add this word to the mix (either as a NOT operator or maybe as an OR). we use the word itself as a key to make it unique $key = $word; $details['wordid'] = 0; } else { $key = $details['wordid'] = $wordids[$word]; } $word_details[$key] = $details; } unset($wordids); unset($words); if (count($word_details) == 1) { $this->process_one_word_rank(array_pop($word_details), $criteria->is_title_only()); } elseif ($has_or_joiner or isset($this->sort['rank'])) { $this->process_existing_words_or($word_details, $criteria->is_title_only()); } else { $this->process_existing_words_and($word_details, $criteria->is_title_only()); } }
/** * Get the search query string in the mysql full text format * * Built to produce the same search strings as the search.php file. * The natural language hack is from search.php * * @param vB_Legacy_Current_User $user user requesting the search * @param vB_Search_Criteria $criteria search criteria to process */ protected function get_search_text($user, $criteria) { // If the user doesn't have permission to search full text boolean mode, // use natural language mode. if ($user->hasPermission('genericpermissions', 'cansearchft_bool')) { $words = $criteria->get_keywords(); $search_text = ""; $word_count = 0; foreach ($words as $word_item) { $word_count++; //The value of the first term is ambiguous. If the second term is //an "or" both the the first and second terms should be treated as //ors. If the second term is an "and" or "not" then the first term //should be an and. if ($word_count == 2 and $word_item['joiner'] != 'OR') { $search_text = "+{$search_text}"; } $word = $word_item['word']; switch ($word_item['joiner']) { case 'OR': // OR is no operator $search_text .= " {$word}"; break; case 'NOT': $search_text .= " -{$word}"; break; case 'AND': // if we didn't have a joiner, default to and // if we didn't have a joiner, default to and default: if ($search_text) { $search_text .= " +{$word}"; } else { //if this is the first token added, then we don't want to assume any //join logic. We need to figure that out on the second term. $search_text = $word; } break; } } //not 100% sure about this, but it matches the results in search.php $search_text = str_replace('"', '\\"', trim($search_text)); } else { $search_text = $criteria->get_raw_keywords(); //if we are using the raw search text, use the whole string as the display text $criteria->set_keyword_display_string('<b><u>' . htmlspecialchars_uni($search_text) . '</u></b>'); $criteria->set_highlights(array($search_text)); } return $search_text; }