protected function createPageSetWithRedirect() { $target = Title::makeTitle(NS_MAIN, 'UTRedirectTarget'); $sourceA = Title::makeTitle(NS_MAIN, 'UTRedirectSourceA'); $sourceB = Title::makeTitle(NS_MAIN, 'UTRedirectSourceB'); self::editPage('UTRedirectTarget', 'api page set test'); self::editPage('UTRedirectSourceA', '#REDIRECT [[UTRedirectTarget]]'); self::editPage('UTRedirectSourceB', '#REDIRECT [[UTRedirectTarget]]'); $request = new FauxRequest(['redirects' => 1]); $context = new RequestContext(); $context->setRequest($request); $main = new ApiMain($context); $pageSet = new ApiPageSet($main); $pageSet->setGeneratorData($sourceA, ['index' => 1]); $pageSet->setGeneratorData($sourceB, ['index' => 3]); $pageSet->populateFromTitles([$sourceA, $sourceB]); return [$target, $pageSet]; }
/** * @param ApiPageSet $resultPageSet */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $search = $params['search']; $limit = $params['limit']; $namespaces = $params['namespace']; $offset = $params['offset']; $searchEngine = MediaWikiServices::getInstance()->newSearchEngine(); $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, ['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 = ['ns' => intval($title->getNamespace()), 'title' => $title->getPrefixedText()]; if ($title->isSpecialPage()) { $vals['special'] = true; } else { $vals['pageid'] = intval($title->getArticleID()); } $fit = $result->addValue(['query', $this->getModuleName()], null, $vals); if (!$fit) { $this->setContinueEnumParameter('offset', $offset + $count - 1); break; } } $result->addIndexedTagName(['query', $this->getModuleName()], $this->getModulePrefix()); } }
/** * @param ApiPageSet $resultPageSet */ private function run($resultPageSet = null) { $params = $this->extractRequestParams(); $search = $params['search']; $limit = $params['limit']; $namespaces = $params['namespace']; $offset = $params['offset']; $searcher = new TitlePrefixSearch(); $titles = $searcher->searchWithVariants($search, $limit + 1, $namespaces, $offset); if ($resultPageSet) { 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()); } }
/** * @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)); } } }