/**
  * 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;
 }