35 private $allowedParams;
38 private $searchEngineConfig;
41 private $searchEngineFactory;
55 parent::__construct( $query, $moduleName,
'sr' );
57 $this->searchEngineConfig = $searchEngineConfig;
58 $this->searchEngineFactory = $searchEngineFactory;
66 $this->run( $resultPageSet );
73 private function run( $resultPageSet =
null ) {
77 $query = $params[
'search'];
78 $what = $params[
'what'];
79 $interwiki = $params[
'interwiki'];
80 $searchInfo = array_fill_keys( $params[
'info'],
true );
81 $prop = array_fill_keys( $params[
'prop'],
true );
85 if ( isset( $params[
'sort'] ) ) {
86 $search->setSort( $params[
'sort'] );
88 $search->setFeatureData(
'rewrite', (
bool)$params[
'enablerewrites'] );
89 $search->setFeatureData(
'interwiki', (
bool)$interwiki );
91 $search->setFeatureData(
'snippets', $this->decideSnippets( $prop ) );
93 $nquery = $search->replacePrefixes( $query );
94 if ( $nquery !== $query ) {
97 get_class( $search ) .
', this was deprecated in MediaWiki 1.32',
101 if ( $what ==
'text' ) {
102 $matches = $search->searchText( $query );
103 } elseif ( $what ==
'title' ) {
104 $matches = $search->searchTitle( $query );
105 } elseif ( $what ==
'nearmatch' ) {
109 ->getNearMatchResultSet( $params[
'search'] );
116 $matches = $search->searchTitle( $query );
124 $matches = $search->searchText( $query );
136 if ( $status->isOK() ) {
137 $this->
getMain()->getErrorFormatter()->addMessagesFromStatus(
145 $this->
dieWithError( [
'apierror-searchdisabled', $what ],
"search-{$what}-disabled" );
150 if ( isset( $searchInfo[
'totalhits'] ) ) {
151 $totalhits =
$matches->getTotalHits();
152 if ( $totalhits !==
null ) {
153 $apiResult->
addValue( [
'query',
'searchinfo' ],
154 'totalhits', $totalhits );
157 if ( isset( $searchInfo[
'suggestion'] ) &&
$matches->hasSuggestion() ) {
158 $apiResult->
addValue( [
'query',
'searchinfo' ],
159 'suggestion',
$matches->getSuggestionQuery() );
160 $apiResult->
addValue( [
'query',
'searchinfo' ],
161 'suggestionsnippet', HtmlArmor::getHtml(
$matches->getSuggestionSnippet() ) );
163 if ( isset( $searchInfo[
'rewrittenquery'] ) &&
$matches->hasRewrittenQuery() ) {
164 $apiResult->
addValue( [
'query',
'searchinfo' ],
165 'rewrittenquery',
$matches->getQueryAfterRewrite() );
166 $apiResult->
addValue( [
'query',
'searchinfo' ],
167 'rewrittenquerysnippet', HtmlArmor::getHtml(
$matches->getQueryAfterRewriteSnippet() ) );
181 if ( $result->isBrokenTitle() || $result->isMissingRevision() ) {
185 $vals = $this->getSearchResultData( $result, $prop );
187 if ( $resultPageSet ===
null ) {
197 $titles[] = $result->getTitle();
198 $data[] = $vals ?: [];
207 $canAddInterwiki = (bool)$params[
'enablerewrites'] && ( $resultPageSet ===
null );
208 if ( $canAddInterwiki ) {
209 $this->addInterwikiResults(
$matches, $apiResult, $prop,
'additional',
210 ISearchResultSet::INLINE_RESULTS );
214 if ( $interwiki && $resultPageSet ===
null ) {
215 $this->addInterwikiResults(
$matches, $apiResult, $prop,
'interwiki',
216 ISearchResultSet::SECONDARY_RESULTS );
219 if ( $resultPageSet ===
null ) {
224 $resultPageSet->setRedirectMergePolicy(
static function ( $current, $new ) {
225 if ( !isset( $current[
'index'] ) || $new[
'index'] < $current[
'index'] ) {
226 $current[
'index'] = $new[
'index'];
230 $resultPageSet->populateFromTitles( $titles );
231 $offset = $params[
'offset'] + 1;
232 foreach ( $titles as $index =>
$title ) {
233 $resultPageSet->setGeneratorData(
235 $data[ $index ] + [
'index' => $index + $offset ]
247 private function getSearchResultData(
SearchResult $result, $prop ) {
249 if ( $result->isBrokenTitle() || $result->isMissingRevision() ) {
255 $title = $result->getTitle();
257 $vals[
'pageid'] =
$title->getArticleID();
259 if ( isset( $prop[
'size'] ) ) {
260 $vals[
'size'] = $result->getByteSize();
262 if ( isset( $prop[
'wordcount'] ) ) {
263 $vals[
'wordcount'] = $result->getWordCount();
265 if ( isset( $prop[
'snippet'] ) ) {
266 $vals[
'snippet'] = $result->getTextSnippet();
268 if ( isset( $prop[
'timestamp'] ) ) {
269 $vals[
'timestamp'] =
wfTimestamp( TS_ISO_8601, $result->getTimestamp() );
271 if ( isset( $prop[
'titlesnippet'] ) ) {
272 $vals[
'titlesnippet'] = $result->getTitleSnippet();
274 if ( isset( $prop[
'categorysnippet'] ) ) {
275 $vals[
'categorysnippet'] = $result->getCategorySnippet();
277 if ( $result->getRedirectTitle() !==
null ) {
278 if ( isset( $prop[
'redirecttitle'] ) ) {
279 $vals[
'redirecttitle'] = $result->getRedirectTitle()->getPrefixedText();
281 if ( isset( $prop[
'redirectsnippet'] ) ) {
282 $vals[
'redirectsnippet'] = $result->getRedirectSnippet();
285 if ( $result->getSectionTitle() !==
null ) {
286 if ( isset( $prop[
'sectiontitle'] ) ) {
287 $vals[
'sectiontitle'] = $result->getSectionTitle()->getFragment();
289 if ( isset( $prop[
'sectionsnippet'] ) ) {
290 $vals[
'sectionsnippet'] = $result->getSectionSnippet();
293 if ( isset( $prop[
'isfilematch'] ) ) {
294 $vals[
'isfilematch'] = $result->isFileMatch();
297 if ( isset( $prop[
'extensiondata'] ) ) {
298 $extra = $result->getExtensionData();
318 private function addInterwikiResults(
324 foreach (
$matches->getInterwikiResults(
$type ) as $interwikiMatches ) {
326 $totalhits += $interwikiMatches->getTotalHits();
328 foreach ( $interwikiMatches as $result ) {
329 $title = $result->getTitle();
330 $vals = $this->getSearchResultData( $result, $prop );
332 $vals[
'namespace'] = $result->getInterwikiNamespaceText();
333 $vals[
'title'] =
$title->getText();
334 $vals[
'url'] =
$title->getFullURL();
340 $result->getInterwikiPrefix()
350 if ( $totalhits !==
null ) {
351 $apiResult->
addValue( [
'query', $section .
'searchinfo' ],
'totalhits', $totalhits );
360 private function decideSnippets( array $prop ): array {
365 if ( isset( $prop[
'titlesnippet'] ) ) {
371 if ( isset( $prop[
'redirectsnippet'] ) || isset( $prop[
'redirecttitle'] ) ) {
372 $fields[] =
'redirect';
374 if ( isset( $prop[
'categorysnippet'] ) ) {
375 $fields[] =
'category';
377 if ( isset( $prop[
'sectionsnippet'] ) || isset( $prop[
'sectiontitle'] ) ) {
378 $fields[] =
'heading';
388 if ( $this->allowedParams !==
null ) {
389 return $this->allowedParams;
394 ParamValidator::PARAM_TYPE => [
401 ParamValidator::PARAM_DEFAULT =>
'totalhits|suggestion|rewrittenquery',
402 ParamValidator::PARAM_TYPE => [
407 ParamValidator::PARAM_ISMULTI =>
true,
410 ParamValidator::PARAM_DEFAULT =>
'size|wordcount|timestamp|snippet',
411 ParamValidator::PARAM_TYPE => [
427 ParamValidator::PARAM_ISMULTI =>
true,
429 EnumDef::PARAM_DEPRECATED_VALUES => [
434 'interwiki' =>
false,
435 'enablerewrites' =>
false,
439 if ( $this->isInGeneratorMode() ) {
440 $this->allowedParams[
'prop'][ParamValidator::PARAM_DEFAULT] =
'';
441 $this->allowedParams[
'info'][ParamValidator::PARAM_DEFAULT] =
'';
446 $alternatives = $this->searchEngineConfig->getSearchTypes();
447 if ( count( $alternatives ) == 1 ) {
448 $this->allowedParams[
'sort'] = [
449 ParamValidator::PARAM_DEFAULT => SearchEngine::DEFAULT_SORT,
450 ParamValidator::PARAM_TYPE => $this->searchEngineFactory->create()->getValidSorts(),
454 return $this->allowedParams;
460 'profile-type' => SearchEngine::FT_QUERY_INDEP_PROFILE_TYPE,
461 'help-message' =>
'apihelp-query+search-param-qiprofile',
468 'action=query&list=search&srsearch=meaning'
469 =>
'apihelp-query+search-example-simple',
470 'action=query&list=search&srwhat=text&srsearch=meaning'
471 =>
'apihelp-query+search-example-text',
472 'action=query&generator=search&gsrsearch=meaning&prop=info'
473 =>
'apihelp-query+search-example-generator',
478 return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Search';
wfDeprecatedMsg( $msg, $version=false, $component=false, $callerOffset=2)
Log a deprecation warning with arbitrary message text.
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
buildSearchEngine(array $params=null)
Build the search engine to use.
buildCommonApiParams( $isScrollable=true)
The set of api parameters that are shared between api calls that call the SearchEngine.
dieWithError( $msg, $code=null, $data=null, $httpCode=0)
Abort execution with an error.
getMain()
Get the main module.
const PARAM_HELP_MSG_PER_VALUE
((string|array|Message)[]) When PARAM_TYPE is an array, this is an array mapping those values to $msg...
getResult()
Get the result object.
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
getModuleName()
Get the name of the module being executed by this instance.
dieStatus(StatusValue $status)
Throw an ApiUsageException based on the Status object.
static addTitleInfo(&$arr, $title, $prefix='')
Add information (title and namespace) about a Title object to a result array.
setContinueEnumParameter( $paramName, $paramValue)
Overridden to set the generator param if in generator mode.
Query module to perform full text search within wiki titles and content.
execute()
Evaluates the parameters, performs the requested query, and sets up the result.
getHelpUrls()
Return links to more detailed help pages about the module.
getExamplesMessages()
Returns usage examples for this module.
__construct(ApiQuery $query, $moduleName, SearchEngineConfig $searchEngineConfig, SearchEngineFactory $searchEngineFactory)
getCacheMode( $params)
Get the cache mode for the data generated by this module.
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
executeGenerator( $resultPageSet)
Execute this module as a generator.
This is the main query class.
This class represents the result of the API operations.
static addMetadataToResultVars( $vars, $forceHash=true)
Add the correct metadata to an array of vars we want to export through the API.
addIndexedTagName( $path, $tag)
Set the tag name for numeric-keyed values in XML format.
addValue( $path, $name, $value, $flags=0)
Add value to the output data at the given path.
Configuration handling class for SearchEngine.
Factory class for SearchEngine.
NOTE: this class is being refactored into an abstract base class.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
trait SearchApi
Traits for API components that use a SearchEngine.
A set of SearchEngine results.