static function getSearchEngine()
 {
     if (!self::$searchEngine) {
         self::$searchEngine = SearchEngine::create();
     }
     return self::$searchEngine;
 }
Esempio n. 2
0
 /**
  * Perform actual update for the entry
  */
 public function doUpdate()
 {
     global $wgDisableSearchUpdate;
     if ($wgDisableSearchUpdate || !$this->id) {
         return;
     }
     foreach (SearchEngine::getSearchTypes() as $type) {
         $search = SearchEngine::create($type);
         if (!$search->supports('search-update')) {
             continue;
         }
         $normalTitle = $this->getNormalizedTitle($search);
         if ($this->getLatestPage() === null) {
             $search->delete($this->id, $normalTitle);
             continue;
         } elseif ($this->content === false) {
             $search->updateTitle($this->id, $normalTitle);
             continue;
         }
         $text = $search->getTextFromContent($this->title, $this->content);
         if (!$search->textAlreadyUpdatedForIndex()) {
             $text = self::updateText($text);
         }
         # Perform the actual update
         $search->update($this->id, $normalTitle, $search->normalizeText($text));
     }
 }
Esempio n. 3
0
 /**
  * Perform actual update for the entry
  */
 public function doUpdate()
 {
     global $wgDisableSearchUpdate;
     if ($wgDisableSearchUpdate || !$this->id) {
         return;
     }
     wfProfileIn(__METHOD__);
     $page = WikiPage::newFromId($this->id, WikiPage::READ_LATEST);
     $indexTitle = Title::indexTitle($this->title->getNamespace(), $this->title->getText());
     foreach (SearchEngine::getSearchTypes() as $type) {
         $search = SearchEngine::create($type);
         if (!$search->supports('search-update')) {
             continue;
         }
         $normalTitle = $search->normalizeText($indexTitle);
         if ($page === null) {
             $search->delete($this->id, $normalTitle);
             continue;
         } elseif ($this->content === false) {
             $search->updateTitle($this->id, $normalTitle);
             continue;
         }
         $text = $search->getTextFromContent($this->title, $this->content);
         if (!$search->textAlreadyUpdatedForIndex()) {
             $text = self::updateText($text);
         }
         # Perform the actual update
         $search->update($this->id, $normalTitle, $search->normalizeText($text));
     }
     wfProfileOut(__METHOD__);
 }
 public function execute($parameters)
 {
     global $wgOut, $wgRequest, $wgDisableTextSearch, $wgScript;
     $this->setHeaders();
     list($limit, $offset) = wfCheckLimits();
     $wgOut->addWikiText(wfMsgForContentNoTrans('proofreadpage_specialpage_text'));
     $this->searchList = null;
     $this->searchTerm = $wgRequest->getText('key');
     $this->suppressSqlOffset = false;
     if (!$wgDisableTextSearch) {
         $self = $this->getTitle();
         $wgOut->addHTML(Xml::openElement('form', array('action' => $wgScript)) . Html::hidden('title', $this->getTitle()->getPrefixedText()) . Xml::input('limit', false, $limit, array('type' => 'hidden')) . Xml::openElement('fieldset') . Xml::element('legend', null, wfMsg('proofreadpage_specialpage_legend')) . Xml::input('key', 20, $this->searchTerm) . ' ' . Xml::submitButton(wfMsg('ilsubmit')) . Xml::closeElement('fieldset') . Xml::closeElement('form'));
         if ($this->searchTerm) {
             $index_namespace = $this->index_namespace;
             $index_ns_index = MWNamespace::getCanonicalIndex(strtolower(str_replace(' ', '_', $index_namespace)));
             $searchEngine = SearchEngine::create();
             $searchEngine->setLimitOffset($limit, $offset);
             $searchEngine->setNamespaces(array($index_ns_index));
             $searchEngine->showRedirects = false;
             $textMatches = $searchEngine->searchText($this->searchTerm);
             $escIndex = preg_quote($index_namespace, '/');
             $this->searchList = array();
             while ($result = $textMatches->next()) {
                 $title = $result->getTitle();
                 if ($title->getNamespace() == $index_ns_index) {
                     array_push($this->searchList, $title->getDBkey());
                 }
             }
             $this->suppressSqlOffset = true;
         }
     }
     parent::execute($parameters);
 }
Esempio n. 5
0
 protected function setUp()
 {
     parent::setUp();
     if (!$this->isWikitextNS(NS_MAIN)) {
         $this->markTestSkipped('Main namespace does not support wikitext.');
     }
     // Avoid special pages from extensions interferring with the tests
     $this->setMwGlobals('wgSpecialPages', array());
     $this->search = SearchEngine::create();
     $this->search->setNamespaces(array());
 }
Esempio n. 6
0
 /**
  * @param ApiPageSet $resultPageSet
  */
 private function run($resultPageSet = null)
 {
     $params = $this->extractRequestParams();
     $search = $params['search'];
     $limit = $params['limit'];
     $namespaces = $params['namespace'];
     $offset = $params['offset'];
     $searchEngine = SearchEngine::create();
     $searchEngine->setLimitOffset($limit + 1, $offset);
     $searchEngine->setNamespaces($namespaces);
     $titles = $searchEngine->extractTitles($searchEngine->completionSearchWithVariants($search));
     if ($resultPageSet) {
         $resultPageSet->setRedirectMergePolicy(function (array $current, array $new) {
             if (!isset($current['index']) || $new['index'] < $current['index']) {
                 $current['index'] = $new['index'];
             }
             return $current;
         });
         if (count($titles) > $limit) {
             $this->setContinueEnumParameter('offset', $offset + $params['limit']);
             array_pop($titles);
         }
         $resultPageSet->populateFromTitles($titles);
         foreach ($titles as $index => $title) {
             $resultPageSet->setGeneratorData($title, array('index' => $index + $offset + 1));
         }
     } else {
         $result = $this->getResult();
         $count = 0;
         foreach ($titles as $title) {
             if (++$count > $limit) {
                 $this->setContinueEnumParameter('offset', $offset + $params['limit']);
                 break;
             }
             $vals = array('ns' => intval($title->getNamespace()), 'title' => $title->getPrefixedText());
             if ($title->isSpecialPage()) {
                 $vals['special'] = true;
             } else {
                 $vals['pageid'] = intval($title->getArticleId());
             }
             $fit = $result->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('offset', $offset + $count - 1);
                 break;
             }
         }
         $result->addIndexedTagName(array('query', $this->getModuleName()), $this->getModulePrefix());
     }
 }
Esempio n. 7
0
 private function run($resultPageSet = null)
 {
     global $wgUser;
     // XX Added to minimize perf issues with full text searching
     if ($wgUser->isAnon()) {
         $this->dieUsage("Search query api is disabled", 'param-search');
     }
     $params = $this->extractRequestParams();
     $limit = $params['limit'];
     $query = $params['search'];
     if (is_null($query) || empty($query)) {
         $this->dieUsage("empty search string is not allowed", 'param-search');
     }
     $search = SearchEngine::create();
     $search->setLimitOffset($limit + 1, $params['offset']);
     $search->setNamespaces($params['namespace']);
     $search->showRedirects = $params['redirects'];
     if ($params['what'] == 'text') {
         $matches = $search->searchText($query);
     } else {
         $matches = $search->searchTitle($query);
     }
     $data = array();
     $count = 0;
     while ($result = $matches->next()) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are additional items to be had. Stop here...
             $this->setContinueEnumParameter('offset', $params['offset'] + $params['limit']);
             break;
         }
         $title = $result->getTitle();
         if (is_null($resultPageSet)) {
             $data[] = array('ns' => intval($title->getNamespace()), 'title' => $title->getPrefixedText());
         } else {
             $data[] = $title;
         }
     }
     if (is_null($resultPageSet)) {
         $result = $this->getResult();
         $result->setIndexedTagName($data, 'p');
         $result->addValue('query', $this->getModuleName(), $data);
     } else {
         $resultPageSet->populateFromTitles($data);
     }
 }
Esempio n. 8
0
 function doUpdate()
 {
     global $wgContLang, $wgDisableSearchUpdate;
     if ($wgDisableSearchUpdate || !$this->mId) {
         return false;
     }
     wfProfileIn(__METHOD__);
     $search = SearchEngine::create();
     $lc = SearchEngine::legalSearchChars() . '&#;';
     if ($this->mText === false) {
         $search->updateTitle($this->mId, $search->normalizeText(Title::indexTitle($this->mNamespace, $this->mTitle)));
         wfProfileOut(__METHOD__);
         return;
     }
     # Language-specific strip/conversion
     $text = $wgContLang->normalizeForSearch($this->mText);
     wfProfileIn(__METHOD__ . '-regexps');
     $text = preg_replace("/<\\/?\\s*[A-Za-z][^>]*?>/", ' ', $wgContLang->lc(" " . $text . " "));
     # Strip HTML markup
     $text = preg_replace("/(^|\\n)==\\s*([^\\n]+)\\s*==(\\s)/sD", "\\1\\2 \\2 \\2\\3", $text);
     # Emphasize headings
     # Strip external URLs
     $uc = "A-Za-z0-9_\\/:.,~%\\-+&;#?!=()@\\x80-\\xFF";
     $protos = "http|https|ftp|mailto|news|gopher";
     $pat = "/(^|[^\\[])({$protos}):[{$uc}]+([^{$uc}]|\$)/";
     $text = preg_replace($pat, "\\1 \\3", $text);
     $p1 = "/([^\\[])\\[({$protos}):[{$uc}]+]/";
     $p2 = "/([^\\[])\\[({$protos}):[{$uc}]+\\s+([^\\]]+)]/";
     $text = preg_replace($p1, "\\1 ", $text);
     $text = preg_replace($p2, "\\1 \\3 ", $text);
     # Internal image links
     $pat2 = "/\\[\\[image:([{$uc}]+)\\.(gif|png|jpg|jpeg)([^{$uc}])/i";
     $text = preg_replace($pat2, " \\1 \\3", $text);
     $text = preg_replace("/([^{$lc}])([{$lc}]+)]]([a-z]+)/", "\\1\\2 \\2\\3", $text);
     # Handle [[game]]s
     # Strip all remaining non-search characters
     $text = preg_replace("/[^{$lc}]+/", " ", $text);
     # Handle 's, s'
     #
     #   $text = preg_replace( "/([{$lc}]+)'s /", "\\1 \\1's ", $text );
     #   $text = preg_replace( "/([{$lc}]+)s' /", "\\1s ", $text );
     #
     # These tail-anchored regexps are insanely slow. The worst case comes
     # when Japanese or Chinese text (ie, no word spacing) is written on
     # a wiki configured for Western UTF-8 mode. The Unicode characters are
     # expanded to hex codes and the "words" are very long paragraph-length
     # monstrosities. On a large page the above regexps may take over 20
     # seconds *each* on a 1GHz-level processor.
     #
     # Following are reversed versions which are consistently fast
     # (about 3 milliseconds on 1GHz-level processor).
     #
     $text = strrev(preg_replace("/ s'([{$lc}]+)/", " s'\\1 \\1", strrev($text)));
     $text = strrev(preg_replace("/ 's([{$lc}]+)/", " s\\1", strrev($text)));
     # Strip wiki '' and '''
     $text = preg_replace("/''[']*/", " ", $text);
     wfProfileOut(__METHOD__ . '-regexps');
     wfRunHooks('SearchUpdate', array($this->mId, $this->mNamespace, $this->mTitle, &$text));
     # Perform the actual update
     $search->update($this->mId, $search->normalizeText(Title::indexTitle($this->mNamespace, $this->mTitle)), $search->normalizeText($text));
     wfProfileOut(__METHOD__);
 }
Esempio n. 9
0
 /**
  * @param $fieldSet String
  */
 public function showResults($fieldSet)
 {
     global $wgOut, $wgUser, $wgContLang, $wgScript, $wgSolrShowRelated, $wgSolrDebug;
     wfProfileIn(__METHOD__);
     $sk = $wgUser->getSkin();
     $this->searchEngine = SearchEngine::create();
     $search =& $this->searchEngine;
     $search->setLimitOffset($this->limit, $this->offset);
     $this->setupPage($fieldSet);
     $t = Title::newFromText($fieldSet->getName());
     //Do we have Title matches
     $fields = $fieldSet->getFields();
     //Build Solr query string form the fields
     if (isset($fields['solrsearch'])) {
         $query = $fields['solrsearch'];
     } else {
         $query = '';
     }
     $firsttime = true;
     $fieldSeperator = $fieldSet->getFieldSeperator();
     foreach ($fields as $key => $value) {
         if ($key != 'solrsearch' && !empty($value)) {
             if ($firsttime) {
                 $query = trim($query) . ' ' . trim(substr($key, 4)) . ':' . '(' . $value . ')';
                 $firsttime = false;
             } else {
                 $query = trim($query) . " {$fieldSeperator} " . trim(substr($key, 4)) . ':' . '(' . $value . ')';
             }
         }
     }
     if (!empty($query)) {
         $query .= $fieldSet->getQuery();
     }
     // TODO: More Exception Handling for Format Exceptions
     try {
         $titleMatches = $search->searchTitle($query);
         if (!$titleMatches instanceof SearchResultTooMany) {
             $textMatches = $search->searchText($query);
         }
         // did you mean... suggestions
         if ($textMatches && $textMatches->hasSuggestion()) {
             $st = SpecialPage::getTitleFor('SolrSearch');
             # mirror Go/Search behaviour of original request ..
             $didYouMeanParams = array('solrsearch' => $textMatches->getSuggestionQuery());
             $stParams = $didYouMeanParams;
             $suggestionSnippet = $textMatches->getSuggestionSnippet();
             if ($suggestionSnippet == '') {
                 $suggestionSnippet = null;
             }
             $suggestLink = $sk->linkKnown($st, $suggestionSnippet, array(), $stParams);
             $this->didYouMeanHtml = '<div class="searchdidyoumean">' . wfMsg('search-suggest', $suggestLink) . '</div>';
         }
     } catch (Exception $exc) {
         #Todo: Catch different Exceptions not just one for all
         $textMatches = false;
         $titleMatches = false;
         $wgOut->addHTML('<p class="solr-error">' . wfMsg('solrstore-error') . '<p\\>');
         if ($wgSolrDebug) {
             $wgOut->addHTML('<p class="solr-error">' . $exc . '<p\\>');
         }
     }
     // start rendering the page
     $wgOut->addHtml(Xml::openElement('form', array('id' => 'solrsearch', 'method' => 'get', 'action' => $wgScript)));
     $wgOut->addHtml(Xml::openElement('table', array('id' => 'mw-search-top-table', 'border' => 0, 'cellpadding' => 0, 'cellspacing' => 0)) . Xml::openElement('tr') . Xml::openElement('td') . "\n" . $this->shortDialog($fieldSet) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::closeElement('table'));
     // Sometimes the search engine knows there are too many hits
     if ($titleMatches instanceof SearchResultTooMany) {
         $wgOut->addWikiText('==' . wfMsg('toomanymatches') . "==\n");
         wfProfileOut(__METHOD__);
         return;
     }
     $filePrefix = $wgContLang->getFormattedNsText(NS_FILE) . ':';
     if (trim($query) === '' || $filePrefix === trim($query)) {
         $wgOut->addHTML($this->formHeader(0, 0));
         $wgOut->addHTML('</form>');
         // Empty query -- straight view of search form
         wfProfileOut(__METHOD__);
         return;
     }
     // Get number of results
     $titleMatchesNum = $titleMatches ? $titleMatches->numRows() : 0;
     $textMatchesNum = $textMatches ? $textMatches->numRows() : 0;
     // Total initial query matches (possible false positives)
     $num = $titleMatchesNum + $textMatchesNum;
     // Get total actual results (after second filtering, if any)
     $numTitleMatches = $titleMatches && !is_null($titleMatches->getTotalHits()) ? $titleMatches->getTotalHits() : $titleMatchesNum;
     $numTextMatches = $textMatches && !is_null($textMatches->getTotalHits()) ? $textMatches->getTotalHits() : $textMatchesNum;
     // get total number of results if backend can calculate it
     $totalRes = 0;
     if ($titleMatches && !is_null($titleMatches->getTotalHits())) {
         $totalRes += $titleMatches->getTotalHits();
     }
     if ($textMatches && !is_null($textMatches->getTotalHits())) {
         $totalRes += $textMatches->getTotalHits();
     }
     // show number of results and current offset
     $wgOut->addHTML($this->formHeader($num, $totalRes));
     $wgOut->addHtml(Xml::closeElement('form'));
     $wgOut->addHtml("<div class='searchresults'>");
     // prev/next links
     if ($num || $this->offset) {
         // Show the create link ahead
         if ($wgSolrShowRelated) {
             $this->showCreateLink($t);
         }
         $prevnext = wfViewPrevNext($this->offset, $this->limit, SpecialPage::getTitleFor('SolrSearch/' . $fieldSet->mName), wfArrayToCGI($fieldSet->mFields), max($titleMatchesNum, $textMatchesNum) < $this->limit);
         wfRunHooks('SpecialSolrSearchResults', array($fieldSet, &$titleMatches, &$textMatches));
     } else {
         wfRunHooks('SpecialSolrSearchNoResults', array($fieldSet));
     }
     if ($titleMatches) {
         if ($numTitleMatches > 0) {
             $wgOut->wrapWikiMsg("==\$1==\n", 'titlematches');
             $wgOut->addHTML($this->showMatches($titleMatches));
         }
         $titleMatches->free();
     }
     if ($textMatches) {
         // output appropriate heading
         if ($numTextMatches > 0 && $numTitleMatches > 0) {
             // if no title matches the heading is redundant
             $wgOut->wrapWikiMsg("==\$1==\n", 'textmatches');
         } elseif ($totalRes == 0) {
             # Don't show the 'no text matches' if we received title matches
             $wgOut->wrapWikiMsg("==\$1==\n", 'notextmatches');
         }
         // show results
         if ($numTextMatches > 0) {
             $wgOut->addHTML($this->showMatches($textMatches));
         }
         $textMatches->free();
     }
     $wgOut->addHtml("</div>");
     if ($num || $this->offset) {
         $wgOut->addHTML("<p class='mw-search-pager-bottom'>{$prevnext}</p>\n");
     }
     wfProfileOut(__METHOD__);
 }
Esempio n. 10
0
 /**
  * Lazy initialization of article text from DB
  */
 protected function initText()
 {
     if (!isset($this->mText)) {
         if ($this->mRevision != null) {
             $this->mText = SearchEngine::create()->getTextFromContent($this->mTitle, $this->mRevision->getContent());
         } else {
             // TODO: can we fetch raw wikitext for commons images?
             $this->mText = '';
         }
     }
 }
Esempio n. 11
0
 private function run($resultPageSet = null)
 {
     $params = $this->extractRequestParams();
     $limit = $params['limit'];
     $query = $params['search'];
     $what = $params['what'];
     if (strval($query) === '') {
         $this->dieUsage("empty search string is not allowed", 'param-search');
     }
     $search = SearchEngine::create();
     $search->setLimitOffset($limit + 1, $params['offset']);
     $search->setNamespaces($params['namespace']);
     $search->showRedirects = $params['redirects'];
     if ($what == 'text') {
         $matches = $search->searchText($query);
     } elseif ($what == 'title') {
         $matches = $search->searchTitle($query);
     } else {
         // We default to title searches; this is a terrible legacy
         // of the way we initially set up the MySQL fulltext-based
         // search engine with separate title and text fields.
         // In the future, the default should be for a combined index.
         $what = 'title';
         $matches = $search->searchTitle($query);
         // Not all search engines support a separate title search,
         // for instance the Lucene-based engine we use on Wikipedia.
         // In this case, fall back to full-text search (which will
         // include titles in it!)
         if (is_null($matches)) {
             $what = 'text';
             $matches = $search->searchText($query);
         }
     }
     if (is_null($matches)) {
         $this->dieUsage("{$what} search is disabled", "search-{$what}-disabled");
     }
     $titles = array();
     $count = 0;
     while ($result = $matches->next()) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are additional items to be had. Stop here...
             $this->setContinueEnumParameter('offset', $params['offset'] + $params['limit']);
             break;
         }
         // Silently skip broken and missing titles
         if ($result->isBrokenTitle() || $result->isMissingRevision()) {
             continue;
         }
         $title = $result->getTitle();
         if (is_null($resultPageSet)) {
             $vals = array();
             ApiQueryBase::addTitleInfo($vals, $title);
             $fit = $this->getResult()->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('offset', $params['offset'] + $count - 1);
                 break;
             }
         } else {
             $titles[] = $title;
         }
     }
     if (is_null($resultPageSet)) {
         $this->getResult()->setIndexedTagName_internal(array('query', $this->getModuleName()), 'p');
     } else {
         $resultPageSet->populateFromTitles($titles);
     }
 }
Esempio n. 12
0
 /**
  * @param $resultPageSet ApiPageSet
  * @return void
  */
 private function run($resultPageSet = null)
 {
     global $wgContLang;
     $params = $this->extractRequestParams();
     // Extract parameters
     $limit = $params['limit'];
     $query = $params['search'];
     $what = $params['what'];
     $searchInfo = array_flip($params['info']);
     $prop = array_flip($params['prop']);
     // Create search engine instance and set options
     $search = isset($params['backend']) && $params['backend'] != self::BACKEND_NULL_PARAM ? SearchEngine::create($params['backend']) : SearchEngine::create();
     $search->setLimitOffset($limit + 1, $params['offset']);
     $search->setNamespaces($params['namespace']);
     $search->showRedirects = $params['redirects'];
     $query = $search->transformSearchTerm($query);
     $query = $search->replacePrefixes($query);
     // Perform the actual search
     if ($what == 'text') {
         $matches = $search->searchText($query);
     } elseif ($what == 'title') {
         $matches = $search->searchTitle($query);
     } elseif ($what == 'nearmatch') {
         $matches = SearchEngine::getNearMatchResultSet($query);
     } else {
         // We default to title searches; this is a terrible legacy
         // of the way we initially set up the MySQL fulltext-based
         // search engine with separate title and text fields.
         // In the future, the default should be for a combined index.
         $what = 'title';
         $matches = $search->searchTitle($query);
         // Not all search engines support a separate title search,
         // for instance the Lucene-based engine we use on Wikipedia.
         // In this case, fall back to full-text search (which will
         // include titles in it!)
         if (is_null($matches)) {
             $what = 'text';
             $matches = $search->searchText($query);
         }
     }
     if (is_null($matches)) {
         $this->dieUsage("{$what} search is disabled", "search-{$what}-disabled");
     } elseif ($matches instanceof Status && !$matches->isGood()) {
         $this->dieUsage($matches->getWikiText(), 'search-error');
     }
     $apiResult = $this->getResult();
     // Add search meta data to result
     if (isset($searchInfo['totalhits'])) {
         $totalhits = $matches->getTotalHits();
         if ($totalhits !== null) {
             $apiResult->addValue(array('query', 'searchinfo'), 'totalhits', $totalhits);
         }
     }
     if (isset($searchInfo['suggestion']) && $matches->hasSuggestion()) {
         $apiResult->addValue(array('query', 'searchinfo'), 'suggestion', $matches->getSuggestionQuery());
     }
     // Add the search results to the result
     $terms = $wgContLang->convertForSearchResult($matches->termMatches());
     $titles = array();
     $count = 0;
     $result = $matches->next();
     while ($result) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are
             // additional items to be had. Stop here...
             $this->setContinueEnumParameter('offset', $params['offset'] + $params['limit']);
             break;
         }
         // Silently skip broken and missing titles
         if ($result->isBrokenTitle() || $result->isMissingRevision()) {
             $result = $matches->next();
             continue;
         }
         $title = $result->getTitle();
         if (is_null($resultPageSet)) {
             $vals = array();
             ApiQueryBase::addTitleInfo($vals, $title);
             if (isset($prop['snippet'])) {
                 $vals['snippet'] = $result->getTextSnippet($terms);
             }
             if (isset($prop['size'])) {
                 $vals['size'] = $result->getByteSize();
             }
             if (isset($prop['wordcount'])) {
                 $vals['wordcount'] = $result->getWordCount();
             }
             if (isset($prop['timestamp'])) {
                 $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $result->getTimestamp());
             }
             if (!is_null($result->getScore()) && isset($prop['score'])) {
                 $vals['score'] = $result->getScore();
             }
             if (isset($prop['titlesnippet'])) {
                 $vals['titlesnippet'] = $result->getTitleSnippet($terms);
             }
             if (!is_null($result->getRedirectTitle())) {
                 if (isset($prop['redirecttitle'])) {
                     $vals['redirecttitle'] = $result->getRedirectTitle();
                 }
                 if (isset($prop['redirectsnippet'])) {
                     $vals['redirectsnippet'] = $result->getRedirectSnippet($terms);
                 }
             }
             if (!is_null($result->getSectionTitle())) {
                 if (isset($prop['sectiontitle'])) {
                     $vals['sectiontitle'] = $result->getSectionTitle()->getFragment();
                 }
                 if (isset($prop['sectionsnippet'])) {
                     $vals['sectionsnippet'] = $result->getSectionSnippet();
                 }
             }
             if (isset($prop['hasrelated']) && $result->hasRelated()) {
                 $vals['hasrelated'] = '';
             }
             // Add item to results and see whether it fits
             $fit = $apiResult->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('offset', $params['offset'] + $count - 1);
                 break;
             }
         } else {
             $titles[] = $title;
         }
         $result = $matches->next();
     }
     if (is_null($resultPageSet)) {
         $apiResult->setIndexedTagName_internal(array('query', $this->getModuleName()), 'p');
     } else {
         $resultPageSet->populateFromTitles($titles);
     }
 }
 /**
  * Return an array of subpages beginning with $search that this special page will accept.
  *
  * @param string $search Prefix to search for
  * @param int $limit Maximum number of results to return (usually 10)
  * @param int $offset Number of results to skip (usually 0)
  * @return string[] Matching subpages
  */
 public function prefixSearchSubpages($search, $limit, $offset)
 {
     $title = Title::newFromText($search, NS_FILE);
     if (!$title || $title->getNamespace() !== NS_FILE) {
         // No prefix suggestion outside of file namespace
         return array();
     }
     $search = SearchEngine::create();
     $search->setLimitOffset($limit, $offset);
     // Autocomplete subpage the same as a normal search, but just for files
     $search->setNamespaces(array(NS_FILE));
     $result = $search->defaultPrefixSearch($search);
     return array_map(function (Title $t) {
         // Remove namespace in search suggestion
         return $t->getText();
     }, $result);
 }
function tagSearch($action, $article)
{
    if ($action != 'tagSearch') {
        return true;
    }
    global $wgRequest, $wgOut;
    wfProfileIn(__METHOD__);
    $wgOut->setArticleBodyOnly(true);
    $query = $wgRequest->getText('q');
    $query = preg_replace("/[\"'<>]/", '', $query);
    $search = SearchEngine::create();
    $search->setLimitOffset(10, 0);
    $search->setNamespaces(array(NS_MAIN));
    $search->showRedirects = true;
    $titleMatches = $search->searchTitle($query);
    $numResults = $titleMatches ? $titleMatches->numRows() : 0;
    if ($numResults > 0) {
        $wgOut->addHTML(wfTagSearchShowMatches($titleMatches));
    }
    wfProfileOut(__METHOD__);
    return false;
}
 /**
  * @param string $term
  * @public
  */
 function showResults($term)
 {
     $fname = 'SpecialSearch::showResults';
     wfProfileIn($fname);
     $this->setupPage($term);
     global $wgOut;
     $wgOut->addWikiMsg('searchresulttext');
     if ('' === trim($term)) {
         // Empty query -- straight view of search form
         $wgOut->setSubtitle('');
         $wgOut->addHTML($this->powerSearchBox($term));
         $wgOut->addHTML($this->powerSearchFocus());
         wfProfileOut($fname);
         return;
     }
     global $wgDisableTextSearch;
     if ($wgDisableTextSearch) {
         global $wgForwardSearchUrl;
         if ($wgForwardSearchUrl) {
             $url = str_replace('$1', urlencode($term), $wgForwardSearchUrl);
             $wgOut->redirect($url);
             return;
         }
         global $wgInputEncoding;
         $wgOut->addHTML(wfMsg('searchdisabled'));
         $wgOut->addHTML(wfMsg('googlesearch', htmlspecialchars($term), htmlspecialchars($wgInputEncoding), htmlspecialchars(wfMsg('searchbutton'))));
         wfProfileOut($fname);
         return;
     }
     $search = SearchEngine::create();
     $search->setLimitOffset($this->limit, $this->offset);
     $search->setNamespaces($this->namespaces);
     $search->showRedirects = $this->searchRedirects;
     $titleMatches = $search->searchTitle($term);
     // Sometimes the search engine knows there are too many hits
     if ($titleMatches instanceof SearchResultTooMany) {
         $wgOut->addWikiText('==' . wfMsg('toomanymatches') . "==\n");
         $wgOut->addHTML($this->powerSearchBox($term));
         $wgOut->addHTML($this->powerSearchFocus());
         wfProfileOut($fname);
         return;
     }
     $textMatches = $search->searchText($term);
     $num = ($titleMatches ? $titleMatches->numRows() : 0) + ($textMatches ? $textMatches->numRows() : 0);
     if ($num > 0) {
         if ($num >= $this->limit) {
             $top = wfShowingResults($this->offset, $this->limit);
         } else {
             $top = wfShowingResultsNum($this->offset, $this->limit, $num);
         }
         $wgOut->addHTML("<p>{$top}</p>\n");
     }
     if ($num || $this->offset) {
         $prevnext = wfViewPrevNext($this->offset, $this->limit, SpecialPage::getTitleFor('Search'), wfArrayToCGI($this->powerSearchOptions(), array('search' => $term)), $num < $this->limit);
         $wgOut->addHTML("<br />{$prevnext}\n");
     }
     if ($titleMatches) {
         if ($titleMatches->numRows()) {
             $wgOut->wrapWikiMsg("==\$1==\n", 'titlematches');
             $wgOut->addHTML($this->showMatches($titleMatches));
         } else {
             $wgOut->wrapWikiMsg("==\$1==\n", 'notitlematches');
         }
         $titleMatches->free();
     }
     if ($textMatches) {
         if ($textMatches->numRows()) {
             $wgOut->wrapWikiMsg("==\$1==\n", 'textmatches');
             $wgOut->addHTML($this->showMatches($textMatches));
         } elseif ($num == 0) {
             # Don't show the 'no text matches' if we received title matches
             $wgOut->wrapWikiMsg("==\$1==\n", 'notextmatches');
         }
         $textMatches->free();
     }
     if ($num == 0) {
         $wgOut->addWikiMsg('nonefound');
     }
     if ($num || $this->offset) {
         $wgOut->addHTML("<p>{$prevnext}</p>\n");
     }
     $wgOut->addHTML($this->powerSearchBox($term));
     wfProfileOut($fname);
 }
Esempio n. 16
0
 /**
  * Perform the search
  *
  * @param string $search Text to search
  * @param int $limit Maximum items to return
  * @param array $namespaces Namespaces to search
  * @param bool $resolveRedir Whether to resolve redirects
  * @param array &$results Put results here. Keys have to be integers.
  */
 protected function search($search, $limit, $namespaces, $resolveRedir, &$results)
 {
     $searchEngine = SearchEngine::create();
     $searchEngine->setLimitOffset($limit);
     $searchEngine->setNamespaces($namespaces);
     $titles = $searchEngine->extractTitles($searchEngine->completionSearchWithVariants($search));
     if (!$titles) {
         return;
     }
     // Special pages need unique integer ids in the return list, so we just
     // assign them negative numbers because those won't clash with the
     // always positive articleIds that non-special pages get.
     $nextSpecialPageId = -1;
     if ($resolveRedir) {
         // Query for redirects
         $redirects = array();
         $lb = new LinkBatch($titles);
         if (!$lb->isEmpty()) {
             $db = $this->getDB();
             $res = $db->select(array('page', 'redirect'), array('page_namespace', 'page_title', 'rd_namespace', 'rd_title'), array('rd_from = page_id', 'rd_interwiki IS NULL OR rd_interwiki = ' . $db->addQuotes(''), $lb->constructSet('page', $db)), __METHOD__);
             foreach ($res as $row) {
                 $redirects[$row->page_namespace][$row->page_title] = array($row->rd_namespace, $row->rd_title);
             }
         }
         // Bypass any redirects
         $seen = array();
         foreach ($titles as $title) {
             $ns = $title->getNamespace();
             $dbkey = $title->getDBkey();
             $from = null;
             if (isset($redirects[$ns][$dbkey])) {
                 list($ns, $dbkey) = $redirects[$ns][$dbkey];
                 $from = $title;
                 $title = Title::makeTitle($ns, $dbkey);
             }
             if (!isset($seen[$ns][$dbkey])) {
                 $seen[$ns][$dbkey] = true;
                 $resultId = $title->getArticleID();
                 if ($resultId === 0) {
                     $resultId = $nextSpecialPageId;
                     $nextSpecialPageId -= 1;
                 }
                 $results[$resultId] = array('title' => $title, 'redirect from' => $from, 'extract' => false, 'extract trimmed' => false, 'image' => false, 'url' => wfExpandUrl($title->getFullURL(), PROTO_CURRENT));
             }
         }
     } else {
         foreach ($titles as $title) {
             $resultId = $title->getArticleId();
             if ($resultId === 0) {
                 $resultId = $nextSpecialPageId;
                 $nextSpecialPageId -= 1;
             }
             $results[$resultId] = array('title' => $title, 'redirect from' => null, 'extract' => false, 'extract trimmed' => false, 'image' => false, 'url' => wfExpandUrl($title->getFullUrl(), PROTO_CURRENT));
         }
     }
 }
 /**
  * @param string $term
  */
 public function showResults($term)
 {
     global $wgOut, $wgUser, $wgDisableTextSearch, $wgContLang, $wgScript;
     wfProfileIn(__METHOD__);
     $sk = $wgUser->getSkin();
     $this->searchEngine = SearchEngine::create();
     $search =& $this->searchEngine;
     $search->setLimitOffset($this->limit, $this->offset);
     $search->setNamespaces($this->namespaces);
     $search->showRedirects = $this->searchRedirects;
     $search->prefix = $this->mPrefix;
     $term = $search->transformSearchTerm($term);
     $this->setupPage($term);
     if ($wgDisableTextSearch) {
         global $wgSearchForwardUrl;
         if ($wgSearchForwardUrl) {
             $url = str_replace('$1', urlencode($term), $wgSearchForwardUrl);
             $wgOut->redirect($url);
             wfProfileOut(__METHOD__);
             return;
         }
         global $wgInputEncoding;
         $wgOut->addHTML(Xml::openElement('fieldset') . Xml::element('legend', null, wfMsg('search-external')) . Xml::element('p', array('class' => 'mw-searchdisabled'), wfMsg('searchdisabled')) . wfMsg('googlesearch', htmlspecialchars($term), htmlspecialchars($wgInputEncoding), htmlspecialchars(wfMsg('searchbutton'))) . Xml::closeElement('fieldset'));
         wfProfileOut(__METHOD__);
         return;
     }
     $t = Title::newFromText($term);
     // fetch search results
     $rewritten = $search->replacePrefixes($term);
     $titleMatches = $search->searchTitle($rewritten);
     if (!$titleMatches instanceof SearchResultTooMany) {
         $textMatches = $search->searchText($rewritten);
     }
     // did you mean... suggestions
     if ($textMatches && $textMatches->hasSuggestion()) {
         $st = SpecialPage::getTitleFor('Search');
         # mirror Go/Search behaviour of original request ..
         $didYouMeanParams = array('search' => $textMatches->getSuggestionQuery());
         if ($this->fulltext != null) {
             $didYouMeanParams['fulltext'] = $this->fulltext;
         }
         $stParams = array_merge($didYouMeanParams, $this->powerSearchOptions());
         $suggestionSnippet = $textMatches->getSuggestionSnippet();
         if ($suggestionSnippet == '') {
             $suggestionSnippet = null;
         }
         $suggestLink = $sk->linkKnown($st, $suggestionSnippet, array(), $stParams);
         $this->didYouMeanHtml = '<div class="searchdidyoumean">' . wfMsg('search-suggest', $suggestLink) . '</div>';
     }
     // start rendering the page
     $wgOut->addHtml(Xml::openElement('form', array('id' => $this->searchAdvanced ? 'powersearch' : 'search', 'method' => 'get', 'action' => $wgScript)));
     $wgOut->addHtml(Xml::openElement('table', array('id' => 'mw-search-top-table', 'border' => 0, 'cellpadding' => 0, 'cellspacing' => 0)) . Xml::openElement('tr') . Xml::openElement('td') . "\n" . $this->shortDialog($term) . Xml::closeElement('td') . Xml::closeElement('tr') . Xml::closeElement('table'));
     // Sometimes the search engine knows there are too many hits
     if ($titleMatches instanceof SearchResultTooMany) {
         $wgOut->addWikiText('==' . wfMsg('toomanymatches') . "==\n");
         wfProfileOut(__METHOD__);
         return;
     }
     $filePrefix = $wgContLang->getFormattedNsText(NS_FILE) . ':';
     if (trim($term) === '' || $filePrefix === trim($term)) {
         $wgOut->addHTML($this->searchFocus());
         $wgOut->addHTML($this->formHeader($term, 0, 0));
         if ($this->searchAdvanced) {
             $wgOut->addHTML($this->powerSearchBox($term));
         }
         $wgOut->addHTML('</form>');
         // Empty query -- straight view of search form
         wfProfileOut(__METHOD__);
         return;
     }
     // Get number of results
     $titleMatchesNum = $titleMatches ? $titleMatches->numRows() : 0;
     $textMatchesNum = $textMatches ? $textMatches->numRows() : 0;
     // Total initial query matches (possible false positives)
     $num = $titleMatchesNum + $textMatchesNum;
     // Get total actual results (after second filtering, if any)
     $numTitleMatches = $titleMatches && !is_null($titleMatches->getTotalHits()) ? $titleMatches->getTotalHits() : $titleMatchesNum;
     $numTextMatches = $textMatches && !is_null($textMatches->getTotalHits()) ? $textMatches->getTotalHits() : $textMatchesNum;
     // get total number of results if backend can calculate it
     $totalRes = 0;
     if ($titleMatches && !is_null($titleMatches->getTotalHits())) {
         $totalRes += $titleMatches->getTotalHits();
     }
     if ($textMatches && !is_null($textMatches->getTotalHits())) {
         $totalRes += $textMatches->getTotalHits();
     }
     // show number of results and current offset
     $wgOut->addHTML($this->formHeader($term, $num, $totalRes));
     if ($this->searchAdvanced) {
         $wgOut->addHTML($this->powerSearchBox($term));
     }
     $wgOut->addHtml(Xml::closeElement('form'));
     $wgOut->addHtml("<div class='searchresults'>");
     // prev/next links
     if ($num || $this->offset) {
         // Show the create link ahead
         $this->showCreateLink($t);
         $prevnext = wfViewPrevNext($this->offset, $this->limit, SpecialPage::getTitleFor('Search'), wfArrayToCGI($this->powerSearchOptions(), array('search' => $term)), max($titleMatchesNum, $textMatchesNum) < $this->limit);
         //$wgOut->addHTML( "<p class='mw-search-pager-top'>{$prevnext}</p>\n" );
         wfRunHooks('SpecialSearchResults', array($term, &$titleMatches, &$textMatches));
     } else {
         wfRunHooks('SpecialSearchNoResults', array($term));
     }
     if ($titleMatches) {
         if ($numTitleMatches > 0) {
             $wgOut->wrapWikiMsg("==\$1==\n", 'titlematches');
             $wgOut->addHTML($this->showMatches($titleMatches));
         }
         $titleMatches->free();
     }
     if ($textMatches) {
         // output appropriate heading
         if ($numTextMatches > 0 && $numTitleMatches > 0) {
             // if no title matches the heading is redundant
             $wgOut->wrapWikiMsg("==\$1==\n", 'textmatches');
         } elseif ($totalRes == 0) {
             # Don't show the 'no text matches' if we received title matches
             # $wgOut->wrapWikiMsg( "==$1==\n", 'notextmatches' );
         }
         // show interwiki results if any
         if ($textMatches->hasInterwikiResults()) {
             $wgOut->addHTML($this->showInterwiki($textMatches->getInterwikiResults(), $term));
         }
         // show results
         if ($numTextMatches > 0) {
             $wgOut->addHTML($this->showMatches($textMatches));
         }
         $textMatches->free();
     }
     if ($num === 0) {
         $wgOut->addWikiMsg('search-nonefound', wfEscapeWikiText($term));
         $this->showCreateLink($t);
     }
     $wgOut->addHtml("</div>");
     if ($num === 0) {
         $wgOut->addHTML($this->searchFocus());
     }
     if ($num || $this->offset) {
         $wgOut->addHTML("<p class='mw-search-pager-bottom'>{$prevnext}</p>\n");
     }
     wfProfileOut(__METHOD__);
 }
Esempio n. 18
0
 /**
  * @param ApiPageSet $resultPageSet
  * @return void
  */
 private function run($resultPageSet = null)
 {
     global $wgContLang;
     $params = $this->extractRequestParams();
     // Extract parameters
     $limit = $params['limit'];
     $query = $params['search'];
     $what = $params['what'];
     $interwiki = $params['interwiki'];
     $searchInfo = array_flip($params['info']);
     $prop = array_flip($params['prop']);
     // Deprecated parameters
     if (isset($prop['hasrelated'])) {
         $this->logFeatureUsage('action=search&srprop=hasrelated');
         $this->setWarning('srprop=hasrelated has been deprecated');
     }
     if (isset($prop['score'])) {
         $this->logFeatureUsage('action=search&srprop=score');
         $this->setWarning('srprop=score has been deprecated');
     }
     // Create search engine instance and set options
     $search = isset($params['backend']) && $params['backend'] != self::BACKEND_NULL_PARAM ? SearchEngine::create($params['backend']) : SearchEngine::create();
     $search->setLimitOffset($limit + 1, $params['offset']);
     $search->setNamespaces($params['namespace']);
     $search->setFeatureData('rewrite', (bool) $params['enablerewrites']);
     $query = $search->transformSearchTerm($query);
     $query = $search->replacePrefixes($query);
     // Perform the actual search
     if ($what == 'text') {
         $matches = $search->searchText($query);
     } elseif ($what == 'title') {
         $matches = $search->searchTitle($query);
     } elseif ($what == 'nearmatch') {
         // near matches must receive the user input as provided, otherwise
         // the near matches within namespaces are lost.
         $matches = SearchEngine::getNearMatchResultSet($params['search']);
     } else {
         // We default to title searches; this is a terrible legacy
         // of the way we initially set up the MySQL fulltext-based
         // search engine with separate title and text fields.
         // In the future, the default should be for a combined index.
         $what = 'title';
         $matches = $search->searchTitle($query);
         // Not all search engines support a separate title search,
         // for instance the Lucene-based engine we use on Wikipedia.
         // In this case, fall back to full-text search (which will
         // include titles in it!)
         if (is_null($matches)) {
             $what = 'text';
             $matches = $search->searchText($query);
         }
     }
     if (is_null($matches)) {
         $this->dieUsage("{$what} search is disabled", "search-{$what}-disabled");
     } elseif ($matches instanceof Status && !$matches->isGood()) {
         $this->dieUsage($matches->getWikiText(), 'search-error');
     }
     if ($resultPageSet === null) {
         $apiResult = $this->getResult();
         // Add search meta data to result
         if (isset($searchInfo['totalhits'])) {
             $totalhits = $matches->getTotalHits();
             if ($totalhits !== null) {
                 $apiResult->addValue(array('query', 'searchinfo'), 'totalhits', $totalhits);
             }
         }
         if (isset($searchInfo['suggestion']) && $matches->hasSuggestion()) {
             $apiResult->addValue(array('query', 'searchinfo'), 'suggestion', $matches->getSuggestionQuery());
             $apiResult->addValue(array('query', 'searchinfo'), 'suggestionsnippet', $matches->getSuggestionSnippet());
         }
         if (isset($searchInfo['rewrittenquery']) && $matches->hasRewrittenQuery()) {
             $apiResult->addValue(array('query', 'searchinfo'), 'rewrittenquery', $matches->getQueryAfterRewrite());
             $apiResult->addValue(array('query', 'searchinfo'), 'rewrittenquerysnippet', $matches->getQueryAfterRewriteSnippet());
         }
     }
     // Add the search results to the result
     $terms = $wgContLang->convertForSearchResult($matches->termMatches());
     $titles = array();
     $count = 0;
     $result = $matches->next();
     while ($result) {
         if (++$count > $limit) {
             // We've reached the one extra which shows that there are
             // additional items to be had. Stop here...
             $this->setContinueEnumParameter('offset', $params['offset'] + $params['limit']);
             break;
         }
         // Silently skip broken and missing titles
         if ($result->isBrokenTitle() || $result->isMissingRevision()) {
             $result = $matches->next();
             continue;
         }
         $title = $result->getTitle();
         if ($resultPageSet === null) {
             $vals = array();
             ApiQueryBase::addTitleInfo($vals, $title);
             if (isset($prop['snippet'])) {
                 $vals['snippet'] = $result->getTextSnippet($terms);
             }
             if (isset($prop['size'])) {
                 $vals['size'] = $result->getByteSize();
             }
             if (isset($prop['wordcount'])) {
                 $vals['wordcount'] = $result->getWordCount();
             }
             if (isset($prop['timestamp'])) {
                 $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $result->getTimestamp());
             }
             if (isset($prop['titlesnippet'])) {
                 $vals['titlesnippet'] = $result->getTitleSnippet();
             }
             if (isset($prop['categorysnippet'])) {
                 $vals['categorysnippet'] = $result->getCategorySnippet();
             }
             if (!is_null($result->getRedirectTitle())) {
                 if (isset($prop['redirecttitle'])) {
                     $vals['redirecttitle'] = $result->getRedirectTitle()->getPrefixedText();
                 }
                 if (isset($prop['redirectsnippet'])) {
                     $vals['redirectsnippet'] = $result->getRedirectSnippet();
                 }
             }
             if (!is_null($result->getSectionTitle())) {
                 if (isset($prop['sectiontitle'])) {
                     $vals['sectiontitle'] = $result->getSectionTitle()->getFragment();
                 }
                 if (isset($prop['sectionsnippet'])) {
                     $vals['sectionsnippet'] = $result->getSectionSnippet();
                 }
             }
             if (isset($prop['isfilematch'])) {
                 $vals['isfilematch'] = $result->isFileMatch();
             }
             // Add item to results and see whether it fits
             $fit = $apiResult->addValue(array('query', $this->getModuleName()), null, $vals);
             if (!$fit) {
                 $this->setContinueEnumParameter('offset', $params['offset'] + $count - 1);
                 break;
             }
         } else {
             $titles[] = $title;
         }
         $result = $matches->next();
     }
     $hasInterwikiResults = false;
     $totalhits = null;
     if ($interwiki && $resultPageSet === null && $matches->hasInterwikiResults()) {
         foreach ($matches->getInterwikiResults() as $matches) {
             $matches = $matches->getInterwikiResults();
             $hasInterwikiResults = true;
             // Include number of results if requested
             if ($resultPageSet === null && isset($searchInfo['totalhits'])) {
                 $totalhits += $matches->getTotalHits();
             }
             $result = $matches->next();
             while ($result) {
                 $title = $result->getTitle();
                 if ($resultPageSet === null) {
                     $vals = array('namespace' => $result->getInterwikiNamespaceText(), 'title' => $title->getText(), 'url' => $title->getFullUrl());
                     // Add item to results and see whether it fits
                     $fit = $apiResult->addValue(array('query', 'interwiki' . $this->getModuleName(), $result->getInterwikiPrefix()), null, $vals);
                     if (!$fit) {
                         // We hit the limit. We can't really provide any meaningful
                         // pagination info so just bail out
                         break;
                     }
                 } else {
                     $titles[] = $title;
                 }
                 $result = $matches->next();
             }
         }
         if ($totalhits !== null) {
             $apiResult->addValue(array('query', 'interwikisearchinfo'), 'totalhits', $totalhits);
         }
     }
     if ($resultPageSet === null) {
         $apiResult->addIndexedTagName(array('query', $this->getModuleName()), 'p');
         if ($hasInterwikiResults) {
             $apiResult->addIndexedTagName(array('query', 'interwiki' . $this->getModuleName()), 'p');
         }
     } else {
         $resultPageSet->populateFromTitles($titles);
         $offset = $params['offset'] + 1;
         foreach ($titles as $index => $title) {
             $resultPageSet->setGeneratorData($title, array('index' => $index + $offset));
         }
     }
 }
Esempio n. 19
0
	/**
	 * @since 1.18
	 *
	 * @return SearchEngine
	 */
	public function getSearchEngine() {
		if ( $this->searchEngine === null ) {
			$this->searchEngine = $this->searchEngineType ?
				SearchEngine::create( $this->searchEngineType ) : SearchEngine::create();
		}
		return $this->searchEngine;
	}
Esempio n. 20
0
 /**
  * @param string $term
  * @public
  */
 function showResults($term)
 {
     wfProfileIn(__METHOD__);
     global $wgOut, $wgUser;
     $sk = $wgUser->getSkin();
     $search = SearchEngine::create();
     $search->setLimitOffset($this->limit, $this->offset);
     $search->setNamespaces($this->namespaces);
     $search->showRedirects = $this->searchRedirects;
     $search->prefix = $this->mPrefix;
     $term = $search->transformSearchTerm($term);
     $this->setupPage($term);
     $rewritten = $search->replacePrefixes($term);
     $titleMatches = $search->searchTitle($rewritten);
     $textMatches = $search->searchText($rewritten);
     // did you mean... suggestions
     if ($textMatches && $textMatches->hasSuggestion()) {
         $st = SpecialPage::getTitleFor('Search');
         $stParams = wfArrayToCGI(array('search' => $textMatches->getSuggestionQuery(), 'fulltext' => wfMsg('search')), $this->powerSearchOptions());
         $suggestLink = $sk->makeKnownLinkObj($st, $textMatches->getSuggestionSnippet(), $stParams);
         $wgOut->addHTML('<div class="searchdidyoumean">' . wfMsg('search-suggest', $suggestLink) . '</div>');
     }
     $wgOut->addWikiMsg('searchresulttext');
     if ('' === trim($term)) {
         // Empty query -- straight view of search form
         $wgOut->setSubtitle('');
         $wgOut->addHTML($this->powerSearchBox($term));
         $wgOut->addHTML($this->powerSearchFocus());
         wfProfileOut(__METHOD__);
         return;
     }
     global $wgDisableTextSearch;
     if ($wgDisableTextSearch) {
         global $wgSearchForwardUrl;
         if ($wgSearchForwardUrl) {
             $url = str_replace('$1', urlencode($term), $wgSearchForwardUrl);
             $wgOut->redirect($url);
             wfProfileOut(__METHOD__);
             return;
         }
         global $wgInputEncoding;
         $wgOut->addHTML(Xml::openElement('fieldset') . Xml::element('legend', null, wfMsg('search-external')) . Xml::element('p', array('class' => 'mw-searchdisabled'), wfMsg('searchdisabled')) . wfMsg('googlesearch', htmlspecialchars($term), htmlspecialchars($wgInputEncoding), htmlspecialchars(wfMsg('searchbutton'))) . Xml::closeElement('fieldset'));
         wfProfileOut(__METHOD__);
         return;
     }
     $wgOut->addHTML($this->shortDialog($term));
     // Sometimes the search engine knows there are too many hits
     if ($titleMatches instanceof SearchResultTooMany) {
         $wgOut->addWikiText('==' . wfMsg('toomanymatches') . "==\n");
         $wgOut->addHTML($this->powerSearchBox($term));
         $wgOut->addHTML($this->powerSearchFocus());
         wfProfileOut(__METHOD__);
         return;
     }
     // show number of results
     $num = ($titleMatches ? $titleMatches->numRows() : 0) + ($textMatches ? $textMatches->numRows() : 0);
     $totalNum = 0;
     if ($titleMatches && !is_null($titleMatches->getTotalHits())) {
         $totalNum += $titleMatches->getTotalHits();
     }
     if ($textMatches && !is_null($textMatches->getTotalHits())) {
         $totalNum += $textMatches->getTotalHits();
     }
     if ($num > 0) {
         if ($totalNum > 0) {
             $top = wfMsgExt('showingresultstotal', array('parseinline'), $this->offset + 1, $this->offset + $num, $totalNum, $num);
         } elseif ($num >= $this->limit) {
             $top = wfShowingResults($this->offset, $this->limit);
         } else {
             $top = wfShowingResultsNum($this->offset, $this->limit, $num);
         }
         $wgOut->addHTML("<p class='mw-search-numberresults'>{$top}</p>\n");
     }
     // prev/next links
     if ($num || $this->offset) {
         $prevnext = wfViewPrevNext($this->offset, $this->limit, SpecialPage::getTitleFor('Search'), wfArrayToCGI($this->powerSearchOptions(), array('search' => $term)), $num < $this->limit);
         $wgOut->addHTML("<p class='mw-search-pager-top'>{$prevnext}</p>\n");
         wfRunHooks('SpecialSearchResults', array($term, &$titleMatches, &$textMatches));
     } else {
         wfRunHooks('SpecialSearchNoResults', array($term));
     }
     if ($titleMatches) {
         if ($titleMatches->numRows()) {
             $wgOut->wrapWikiMsg("==\$1==\n", 'titlematches');
             $wgOut->addHTML($this->showMatches($titleMatches));
         }
         $titleMatches->free();
     }
     if ($textMatches) {
         // output appropriate heading
         if ($textMatches->numRows()) {
             if ($titleMatches) {
                 $wgOut->wrapWikiMsg("==\$1==\n", 'textmatches');
             } else {
                 // if no title matches the heading is redundant
                 $wgOut->addHTML("<hr/>");
             }
         } elseif ($num == 0) {
             # Don't show the 'no text matches' if we received title matches
             $wgOut->wrapWikiMsg("==\$1==\n", 'notextmatches');
         }
         // show interwiki results if any
         if ($textMatches->hasInterwikiResults()) {
             $wgOut->addHTML($this->showInterwiki($textMatches->getInterwikiResults(), $term));
         }
         // show results
         if ($textMatches->numRows()) {
             $wgOut->addHTML($this->showMatches($textMatches));
         }
         $textMatches->free();
     }
     if ($num == 0) {
         $wgOut->addWikiMsg('nonefound');
     }
     if ($num || $this->offset) {
         $wgOut->addHTML("<p class='mw-search-pager-bottom'>{$prevnext}</p>\n");
     }
     $wgOut->addHTML($this->powerSearchBox($term));
     wfProfileOut(__METHOD__);
 }
 /**
  * Generate a MATCH condition
  * @param $arr array $m{Incl,Excl}{Text,Cats}
  * @return string A MATCH condition
  */
 protected function getMatchString($arr)
 {
     $conds = array();
     $searchEngine = SearchEngine::create();
     foreach ($arr as $a) {
         $subconds = array();
         foreach ((array) $a as $b) {
             if (is_array($b)) {
                 $m = $this->getMatchString($b);
                 if (!empty($m)) {
                     $subconds[] = "+({$m})";
                 }
             } else {
                 global $wgContLang;
                 $s = $wgContLang->normalizeForSearch($b);
                 $s = $searchEngine->normalizeText($s);
                 $s = $this->mDb->strencode($s);
                 # If $s contains spaces or ( ) :, quote it
                 if (strpos($s, ' ') !== false || strpos($s, '(') !== false || strpos($s, ')') !== false || strpos($s, ':') !== false) {
                     $s = "\"{$s}\"";
                 }
                 if (!empty($s)) {
                     $subconds[] = "+{$s}";
                 }
             }
         }
         $sc = implode(' ', $subconds);
         if (!empty($sc)) {
             $conds[] = "({$sc})";
         }
     }
     return implode(' ', $conds);
 }
Esempio n. 22
0
 /**
  * @param string $term
  * @access public
  */
 function showResults($term)
 {
     $fname = 'SpecialSearch::showResults';
     wfProfileIn($fname);
     $this->setupPage($term);
     global $wgUser, $wgOut;
     $sk = $wgUser->getSkin();
     $wgOut->addWikiText(wfMsg('searchresulttext'));
     #if ( !$this->parseQuery() ) {
     if ('' === trim($term)) {
         $wgOut->setSubtitle('');
         $wgOut->addHTML($this->powerSearchBox($term));
         wfProfileOut($fname);
         return;
     }
     global $wgDisableTextSearch;
     if ($wgDisableTextSearch) {
         global $wgForwardSearchUrl;
         if ($wgForwardSearchUrl) {
             $url = str_replace('$1', urlencode($term), $wgForwardSearchUrl);
             $wgOut->redirect($url);
             return;
         }
         global $wgInputEncoding;
         $wgOut->addHTML(wfMsg('searchdisabled'));
         $wgOut->addHTML(wfMsg('googlesearch', htmlspecialchars($term), htmlspecialchars($wgInputEncoding), htmlspecialchars(wfMsg('search'))));
         wfProfileOut($fname);
         return;
     }
     $search =& SearchEngine::create();
     $search->setLimitOffset($this->limit, $this->offset);
     $search->setNamespaces($this->namespaces);
     $titleMatches = $search->searchTitle($term);
     $textMatches = $search->searchText($term);
     $num = ($titleMatches ? $titleMatches->numRows() : 0) + ($textMatches ? $textMatches->numRows() : 0);
     if ($num >= $this->limit) {
         $top = wfShowingResults($this->offset, $this->limit);
     } else {
         $top = wfShowingResultsNum($this->offset, $this->limit, $num);
     }
     $wgOut->addHTML("<p>{$top}</p>\n");
     if ($num || $this->offset) {
         $prevnext = wfViewPrevNext($this->offset, $this->limit, 'Special:Search', wfArrayToCGI($this->powerSearchOptions(), array('search' => $term)));
         $wgOut->addHTML("<br />{$prevnext}\n");
     }
     if ($titleMatches) {
         if ($titleMatches->numRows()) {
             $wgOut->addWikiText('==' . wfMsg('titlematches') . "==\n");
             $wgOut->addHTML($this->showMatches($titleMatches));
         } else {
             $wgOut->addWikiText('==' . wfMsg('notitlematches') . "==\n");
         }
     }
     if ($textMatches) {
         if ($textMatches->numRows()) {
             $wgOut->addWikiText('==' . wfMsg('textmatches') . "==\n");
             $wgOut->addHTML($this->showMatches($textMatches));
         } elseif ($num == 0) {
             # Don't show the 'no text matches' if we received title matches
             $wgOut->addWikiText('==' . wfMsg('notextmatches') . "==\n");
         }
     }
     if ($num == 0) {
         $wgOut->addWikiText(wfMsg('nonefound'));
     }
     if ($num || $this->offset) {
         $wgOut->addHTML("<p>{$prevnext}</p>\n");
     }
     $wgOut->addHTML($this->powerSearchBox($term));
     wfProfileOut($fname);
 }
	function search( &$serverOptions ) {
		$serverOptions['namespaces']['http://subversion.tigris.org/xmlns/dav/'] = 'V';

		$status = array();

		$search = SearchEngine::create();

		# TODO: Use (int)$wgUser->getOption( 'searchlimit' );
		$search->setLimitOffset( MW_SEARCH_LIMIT );

		$results = $search->searchText( $serverOptions['xpath']->evaluate( 'string(/D:searchrequest/D:basicsearch/D:where/D:contains)' ) );

		while ( ( $result = $results->next() ) !== false ) {
			$title = $result->getTitle();
			$revision = Revision::newFromTitle( $title );

			$response = array();
			$response['path'] = 'webdav.php/' . $title->getPrefixedUrl();
			$response['props'][] = WebDavServer::mkprop( 'checked-in', $this->getUrl( array( 'path' => 'deltav.php/ver/' . $revision->getId() ) ) );
			$response['props'][] = WebDavServer::mkprop( 'displayname', $title->getText() );
			$response['props'][] = WebDavServer::mkprop( 'getcontentlength', $revision->getSize() );
			$response['props'][] = WebDavServer::mkprop( 'getcontenttype', 'text/x-wiki' );
			$response['props'][] = WebDavServer::mkprop( 'getlastmodified', wfTimestamp( TS_UNIX, $revision->mTimestamp ) );
			$response['props'][] = WebDavServer::mkprop( 'resourcetype', null );
			$response['props'][] = WebDavServer::mkprop( 'version-controlled-configuration', $this->getUrl( array( 'path' => 'deltav.php/vcc/default' ) ) );

			$response['props'][] = WebDavServer::mkprop( 'http://subversion.tigris.org/xmlns/dav/', 'baseline-relative-path', $title->getFullUrl() );
			$response['score'] = $result->getScore();

			$status[] = $response;
		}

		# TODO: Check if we exceed our limit
		#$response = array();
		#$response['status'] = '507 Insufficient Storage';

		#$status[] = $response;

		return $status;
	}
Esempio n. 24
0
 /**
  * Perform a regular substring search for prefixSearchSubpages
  * @param string $search Prefix to search for
  * @param int $limit Maximum number of results to return (usually 10)
  * @param int $offset Number of results to skip (usually 0)
  * @return string[] Matching subpages
  */
 protected function prefixSearchString($search, $limit, $offset)
 {
     $title = Title::newFromText($search);
     if (!$title || !$title->canExist()) {
         // No prefix suggestion in special and media namespace
         return array();
     }
     $search = SearchEngine::create();
     $search->setLimitOffset($limit, $offset);
     $search->setNamespaces(array());
     $result = $search->defaultPrefixSearch($search);
     return array_map(function (Title $t) {
         return $t->getPrefixedText();
     }, $result);
 }