private function decideCluster(SearchConfig $config)
 {
     $cluster = $this->getOption('cluster', null);
     if ($cluster === null) {
         return null;
     }
     if ($config->has('CirrusSearchServers')) {
         $this->error('Not configured for cluster operations.', 1);
     }
     $hosts = $config->getElement('CirrusSearchClusters', $cluster);
     if ($hosts === null) {
         $this->error('Unknown cluster.', 1);
     }
     return $cluster;
 }
 /**
  * @param string $query
  * @param boolean $isRescore
  * @return \Elastica\Query\Simple
  */
 public function wrapInSaferIfPossible($query, $isRescore)
 {
     // @todo: move this code to a common base class when Filters is refactored as non-static
     $saferQuery = $this->config->getElement('CirrusSearchWikimediaExtraPlugin', 'safer');
     if (is_null($saferQuery)) {
         return $query;
     }
     $saferQuery['query'] = $query->toArray();
     $tooLargeAction = $isRescore ? 'convert_to_match_all_query' : 'convert_to_term_queries';
     $saferQuery['phrase']['phrase_too_large_action'] = $tooLargeAction;
     return new \Elastica\Query\Simple(array('safer' => $saferQuery));
 }
 /**
  * Is there more then one namespace in the provided index type?
  * @var string $indexType an index type
  * @return false|integer false if the number of indexes is unknown, an integer if it is known
  */
 public function namespacesInIndexType($indexType)
 {
     if ($indexType === self::GENERAL_INDEX_TYPE) {
         return false;
     }
     $mappings = $this->config->get('CirrusSearchNamespaceMappings');
     $count = count(array_keys($mappings, $indexType));
     if ($indexType === self::CONTENT_INDEX_TYPE) {
         // The content namespace includes everything set in the mappings to content (count right now)
         // Plus everything in wgContentNamespaces that isn't already in namespace mappings
         $contentNamespaces = $this->config->get('ContentNamespaces');
         $count += count(array_diff($contentNamespaces, array_keys($mappings)));
     }
     return $count;
 }
 /**
  * Get the weight of a namespace.
  * @param int $namespace the namespace
  * @return float the weight of the namespace
  */
 private function getBoostForNamespace($namespace)
 {
     if ($this->normalizedNamespaceWeights === null) {
         $this->normalizedNamespaceWeights = array();
         foreach ($this->config->get('CirrusSearchNamespaceWeights') as $ns => $weight) {
             if (is_string($ns)) {
                 $ns = $this->language->getNsIndex($ns);
                 // Ignore namespaces that don't exist.
                 if ($ns === false) {
                     continue;
                 }
             }
             // Now $ns should always be an integer.
             $this->normalizedNamespaceWeights[$ns] = $weight;
         }
     }
     if (isset($this->normalizedNamespaceWeights[$namespace])) {
         return $this->normalizedNamespaceWeights[$namespace];
     }
     if (MWNamespace::isSubject($namespace)) {
         if ($namespace === NS_MAIN) {
             return 1;
         }
         return $this->config->get('CirrusSearchDefaultNamespaceWeight');
     }
     $subjectNs = MWNamespace::getSubject($namespace);
     if (isset($this->normalizedNamespaceWeights[$subjectNs])) {
         return $this->config->get('CirrusSearchTalkNamespaceWeight') * $this->normalizedNamespaceWeights[$subjectNs];
     }
     if ($namespace === NS_TALK) {
         return $this->config->get('CirrusSearchTalkNamespaceWeight');
     }
     return $this->config->get('CirrusSearchDefaultNamespaceWeight') * $this->config->get('CirrusSearchTalkNamespaceWeight');
 }
 /**
  * prepare the list of suggest requests used for geo context suggestions
  * This method will merge $this->config->get( 'CirrusSearchCompletionSettings and
  * $this->config->get( 'CirrusSearchCompletionGeoContextSettings
  * @param array $context user's geo context
  * @return array of suggest request profiles
  */
 private function prepareGeoContextSuggestProfiles()
 {
     $profiles = array();
     foreach ($this->config->get('CirrusSearchCompletionGeoContextSettings') as $geoname => $geoprof) {
         foreach ($this->config->get('CirrusSearchCompletionSettings') as $sugname => $sugprof) {
             if (!in_array($sugname, $geoprof['with'])) {
                 continue;
             }
             $profile = $sugprof;
             $profile['field'] .= $geoprof['field_suffix'];
             $profile['discount'] *= $geoprof['discount'];
             $profile['context'] = array('location' => array('lat' => $this->context['geo']['lat'], 'lon' => $this->context['geo']['lon'], 'precision' => $geoprof['precision']));
             $profiles["{$sugname}-{$geoname}"] = $profile;
         }
     }
     return $profiles;
 }
 private function searchTextReal($term, SearchConfig $config = null)
 {
     global $wgCirrusSearchInterwikiSources;
     // Convert the unicode character 'idiographic whitespace' into standard
     // whitespace.  Cirrussearch treats them both as normal whitespace, but
     // the preceding isn't appropriatly trimmed.
     $term = trim(str_replace(" ", " ", $term));
     // No searching for nothing!  That takes forever!
     if (!$term) {
         return null;
     }
     $context = RequestContext::getMain();
     $request = $context->getRequest();
     $user = $context->getUser();
     if ($config) {
         $this->indexBaseName = $config->getWikiId();
     }
     $searcher = new Searcher($this->connection, $this->offset, $this->limit, $config, $this->namespaces, $user, $this->indexBaseName);
     // Ignore leading ~ because it is used to force displaying search results but not to effect them
     if (substr($term, 0, 1) === '~') {
         $term = substr($term, 1);
         $searcher->addSuggestPrefix('~');
     }
     // TODO remove this when we no longer have to support core versions without
     // Ie946150c6796139201221dfa6f7750c210e97166
     if (method_exists($this, 'getSort')) {
         $searcher->setSort($this->getSort());
     }
     $dumpQuery = $request && $request->getVal('cirrusDumpQuery') !== null;
     $searcher->setReturnQuery($dumpQuery);
     $dumpResult = $request && $request->getVal('cirrusDumpResult') !== null;
     $searcher->setDumpResult($dumpResult);
     $returnExplain = $request && $request->getVal('cirrusExplain') !== null;
     $searcher->setReturnExplain($returnExplain);
     // Delegate to either searchText or moreLikeThisArticle and dump the result into $status
     if (substr($term, 0, strlen(self::MORE_LIKE_THIS_PREFIX)) === self::MORE_LIKE_THIS_PREFIX) {
         $term = substr($term, strlen(self::MORE_LIKE_THIS_PREFIX));
         $status = $this->moreLikeThis($term, $searcher, Searcher::MORE_LIKE_THESE_NONE);
     } else {
         if (substr($term, 0, strlen(self::MORE_LIKE_THIS_JUST_WIKIBASE_PREFIX)) === self::MORE_LIKE_THIS_JUST_WIKIBASE_PREFIX) {
             $term = substr($term, strlen(self::MORE_LIKE_THIS_JUST_WIKIBASE_PREFIX));
             $status = $this->moreLikeThis($term, $searcher, Searcher::MORE_LIKE_THESE_ONLY_WIKIBASE);
         } else {
             # Namespace lookup should not be done for morelike special syntax (T111244)
             if ($this->lastNamespacePrefix) {
                 $searcher->addSuggestPrefix($this->lastNamespacePrefix);
             } else {
                 $searcher->updateNamespacesFromQuery($term);
             }
             $highlightingConfig = FullTextResultsType::HIGHLIGHT_ALL;
             if ($request) {
                 if ($request->getVal('cirrusSuppressSuggest') !== null) {
                     $this->showSuggestion = false;
                 }
                 if ($request->getVal('cirrusSuppressTitleHighlight') !== null) {
                     $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_TITLE;
                 }
                 if ($request->getVal('cirrusSuppressAltTitle') !== null) {
                     $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_ALT_TITLE;
                 }
                 if ($request->getVal('cirrusSuppressSnippet') !== null) {
                     $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_SNIPPET;
                 }
                 if ($request->getVal('cirrusHighlightDefaultSimilarity') === 'no') {
                     $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_WITH_DEFAULT_SIMILARITY;
                 }
                 if ($request->getVal('cirrusHighlightAltTitleWithPostings') === 'no') {
                     $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_ALT_TITLES_WITH_POSTINGS;
                 }
             }
             if ($this->namespaces && !in_array(NS_FILE, $this->namespaces)) {
                 $highlightingConfig ^= FullTextResultsType::HIGHLIGHT_FILE_TEXT;
             }
             $searcher->setResultsType(new FullTextResultsType($highlightingConfig, $config ? $config->getWikiCode() : ''));
             $status = $searcher->searchText($term, $this->showSuggestion);
         }
     }
     if ($dumpQuery || $dumpResult) {
         // When dumping the query we skip _everything_ but echoing the query.
         $context->getOutput()->disable();
         $request->response()->header('Content-type: application/json; charset=UTF-8');
         if ($status->getValue() === null) {
             echo '{}';
         } else {
             echo json_encode($status->getValue());
         }
         exit;
     }
     $this->lastSearchMetrics = $searcher->getSearchMetrics();
     // Add interwiki results, if we have a sane result
     // Note that we have no way of sending warning back to the user.  In this case all warnings
     // are logged when they are added to the status object so we just ignore them here....
     if ($status->isOK() && $wgCirrusSearchInterwikiSources && $status->getValue() && method_exists($status->getValue(), 'addInterwikiResults')) {
         // @todo @fixme: This should absolutely be a multisearch. I knew this when I
         // wrote the code but Searcher needs some refactoring first.
         foreach ($wgCirrusSearchInterwikiSources as $interwiki => $index) {
             $iwSearch = new InterwikiSearcher($this->connection, $this->namespaces, $user, $index, $interwiki);
             $interwikiResult = $iwSearch->getInterwikiResults($term);
             if ($interwikiResult) {
                 $status->getValue()->addInterwikiResults($interwikiResult);
             }
         }
     }
     // For historical reasons all callers of searchText interpret any Status return as an error
     // so we must unwrap all OK statuses.  Note that $status can be "good" and still contain null
     // since that is interpreted as no results.
     return $status->isOk() ? $status->getValue() : $status;
 }