Completed
Branch master (02e057)
by
unknown
27:42
created

ApiQuerySearch::getSearchProfileParams()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 6
rs 9.4285
1
<?php
2
/**
3
 *
4
 *
5
 * Created on July 30, 2007
6
 *
7
 * Copyright © 2007 Yuri Astrakhan "<Firstname><Lastname>@gmail.com"
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License along
20
 * with this program; if not, write to the Free Software Foundation, Inc.,
21
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
 * http://www.gnu.org/copyleft/gpl.html
23
 *
24
 * @file
25
 */
26
27
use MediaWiki\MediaWikiServices;
28
29
/**
30
 * Query module to perform full text search within wiki titles and content
31
 *
32
 * @ingroup API
33
 */
34
class ApiQuerySearch extends ApiQueryGeneratorBase {
35
	use SearchApi;
36
37
	/** @var array list of api allowed params */
38
	private $allowedParams;
39
40
	/**
41
	 * When $wgSearchType is null, $wgSearchAlternatives[0] is null. Null isn't
42
	 * a valid option for an array for PARAM_TYPE, so we'll use a fake name
43
	 * that can't possibly be a class name and describes what the null behavior
44
	 * does
45
	 */
46
	const BACKEND_NULL_PARAM = 'database-backed';
47
48
	public function __construct( ApiQuery $query, $moduleName ) {
49
		parent::__construct( $query, $moduleName, 'sr' );
50
	}
51
52
	public function execute() {
53
		$this->run();
54
	}
55
56
	public function executeGenerator( $resultPageSet ) {
57
		$this->run( $resultPageSet );
58
	}
59
60
	/**
61
	 * @param ApiPageSet $resultPageSet
62
	 * @return void
63
	 */
64
	private function run( $resultPageSet = null ) {
65
		global $wgContLang;
66
		$params = $this->extractRequestParams();
67
68
		if ( isset( $params['backend'] ) && $params['backend'] == self::BACKEND_NULL_PARAM ) {
69
			unset( $params['backend'] );
70
		}
71
72
		// Extract parameters
73
		$query = $params['search'];
74
		$what = $params['what'];
75
		$interwiki = $params['interwiki'];
76
		$searchInfo = array_flip( $params['info'] );
77
		$prop = array_flip( $params['prop'] );
78
79
		// Deprecated parameters
80
		if ( isset( $prop['hasrelated'] ) ) {
81
			$this->logFeatureUsage( 'action=search&srprop=hasrelated' );
82
			$this->setWarning( 'srprop=hasrelated has been deprecated' );
83
		}
84
		if ( isset( $prop['score'] ) ) {
85
			$this->logFeatureUsage( 'action=search&srprop=score' );
86
			$this->setWarning( 'srprop=score has been deprecated' );
87
		}
88
89
		// Create search engine instance and set options
90
		$search = $this->buildSearchEngine( $params );
91
		$search->setFeatureData( 'rewrite', (bool)$params['enablerewrites'] );
92
93
		$query = $search->transformSearchTerm( $query );
94
		$query = $search->replacePrefixes( $query );
95
96
		// Perform the actual search
97
		if ( $what == 'text' ) {
98
			$matches = $search->searchText( $query );
99
		} elseif ( $what == 'title' ) {
100
			$matches = $search->searchTitle( $query );
101
		} elseif ( $what == 'nearmatch' ) {
102
			// near matches must receive the user input as provided, otherwise
103
			// the near matches within namespaces are lost.
104
			$matches = $search->getNearMatcher( $this->getConfig() )
105
				->getNearMatchResultSet( $params['search'] );
106
		} else {
107
			// We default to title searches; this is a terrible legacy
108
			// of the way we initially set up the MySQL fulltext-based
109
			// search engine with separate title and text fields.
110
			// In the future, the default should be for a combined index.
111
			$what = 'title';
112
			$matches = $search->searchTitle( $query );
113
114
			// Not all search engines support a separate title search,
115
			// for instance the Lucene-based engine we use on Wikipedia.
116
			// In this case, fall back to full-text search (which will
117
			// include titles in it!)
118
			if ( is_null( $matches ) ) {
119
				$what = 'text';
120
				$matches = $search->searchText( $query );
121
			}
122
		}
123
		if ( is_null( $matches ) ) {
124
			$this->dieUsage( "{$what} search is disabled", "search-{$what}-disabled" );
125
		} elseif ( $matches instanceof Status && !$matches->isGood() ) {
126
			$this->dieUsage( $matches->getWikiText( false, false, 'en' ), 'search-error' );
127
		}
128
129
		if ( $resultPageSet === null ) {
130
			$apiResult = $this->getResult();
131
			// Add search meta data to result
132
			if ( isset( $searchInfo['totalhits'] ) ) {
133
				$totalhits = $matches->getTotalHits();
0 ignored issues
show
Bug introduced by
The method getTotalHits does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
134
				if ( $totalhits !== null ) {
135
					$apiResult->addValue( [ 'query', 'searchinfo' ],
136
						'totalhits', $totalhits );
137
				}
138
			}
139
			if ( isset( $searchInfo['suggestion'] ) && $matches->hasSuggestion() ) {
0 ignored issues
show
Bug introduced by
The method hasSuggestion does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
140
				$apiResult->addValue( [ 'query', 'searchinfo' ],
141
					'suggestion', $matches->getSuggestionQuery() );
0 ignored issues
show
Bug introduced by
The method getSuggestionQuery does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
142
				$apiResult->addValue( [ 'query', 'searchinfo' ],
143
					'suggestionsnippet', $matches->getSuggestionSnippet() );
0 ignored issues
show
Bug introduced by
The method getSuggestionSnippet does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
144
			}
145
			if ( isset( $searchInfo['rewrittenquery'] ) && $matches->hasRewrittenQuery() ) {
0 ignored issues
show
Bug introduced by
The method hasRewrittenQuery does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
146
				$apiResult->addValue( [ 'query', 'searchinfo' ],
147
					'rewrittenquery', $matches->getQueryAfterRewrite() );
0 ignored issues
show
Bug introduced by
The method getQueryAfterRewrite does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
148
				$apiResult->addValue( [ 'query', 'searchinfo' ],
149
					'rewrittenquerysnippet', $matches->getQueryAfterRewriteSnippet() );
0 ignored issues
show
Bug introduced by
The method getQueryAfterRewriteSnippet does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
150
			}
151
		}
152
153
		// Add the search results to the result
154
		$terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
0 ignored issues
show
Bug introduced by
The method termMatches does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
155
		$titles = [];
156
		$count = 0;
157
		$result = $matches->next();
0 ignored issues
show
Bug introduced by
The method next does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
158
		$limit = $params['limit'];
159
160
		while ( $result ) {
161 View Code Duplication
			if ( ++$count > $limit ) {
162
				// We've reached the one extra which shows that there are
163
				// additional items to be had. Stop here...
164
				$this->setContinueEnumParameter( 'offset', $params['offset'] + $params['limit'] );
165
				break;
166
			}
167
168
			// Silently skip broken and missing titles
169
			if ( $result->isBrokenTitle() || $result->isMissingRevision() ) {
170
				$result = $matches->next();
171
				continue;
172
			}
173
174
			$title = $result->getTitle();
175
			if ( $resultPageSet === null ) {
176
				$vals = [];
177
				ApiQueryBase::addTitleInfo( $vals, $title );
178
179
				if ( isset( $prop['snippet'] ) ) {
180
					$vals['snippet'] = $result->getTextSnippet( $terms );
181
				}
182
				if ( isset( $prop['size'] ) ) {
183
					$vals['size'] = $result->getByteSize();
184
				}
185
				if ( isset( $prop['wordcount'] ) ) {
186
					$vals['wordcount'] = $result->getWordCount();
187
				}
188
				if ( isset( $prop['timestamp'] ) ) {
189
					$vals['timestamp'] = wfTimestamp( TS_ISO_8601, $result->getTimestamp() );
190
				}
191
				if ( isset( $prop['titlesnippet'] ) ) {
192
					$vals['titlesnippet'] = $result->getTitleSnippet();
193
				}
194
				if ( isset( $prop['categorysnippet'] ) ) {
195
					$vals['categorysnippet'] = $result->getCategorySnippet();
196
				}
197
				if ( !is_null( $result->getRedirectTitle() ) ) {
198
					if ( isset( $prop['redirecttitle'] ) ) {
199
						$vals['redirecttitle'] = $result->getRedirectTitle()->getPrefixedText();
200
					}
201
					if ( isset( $prop['redirectsnippet'] ) ) {
202
						$vals['redirectsnippet'] = $result->getRedirectSnippet();
203
					}
204
				}
205
				if ( !is_null( $result->getSectionTitle() ) ) {
206
					if ( isset( $prop['sectiontitle'] ) ) {
207
						$vals['sectiontitle'] = $result->getSectionTitle()->getFragment();
208
					}
209
					if ( isset( $prop['sectionsnippet'] ) ) {
210
						$vals['sectionsnippet'] = $result->getSectionSnippet();
211
					}
212
				}
213
				if ( isset( $prop['isfilematch'] ) ) {
214
					$vals['isfilematch'] = $result->isFileMatch();
215
				}
216
217
				// Add item to results and see whether it fits
218
				$fit = $apiResult->addValue( [ 'query', $this->getModuleName() ],
0 ignored issues
show
Bug introduced by
The variable $apiResult does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
219
					null, $vals );
220
				if ( !$fit ) {
221
					$this->setContinueEnumParameter( 'offset', $params['offset'] + $count - 1 );
222
					break;
223
				}
224
			} else {
225
				$titles[] = $title;
226
			}
227
228
			$result = $matches->next();
229
		}
230
231
		$hasInterwikiResults = false;
232
		$totalhits = null;
233
		if ( $interwiki && $resultPageSet === null && $matches->hasInterwikiResults() ) {
0 ignored issues
show
Bug introduced by
The method hasInterwikiResults does only exist in SearchResultSet, but not in Status.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
234
			foreach ( $matches->getInterwikiResults() as $matches ) {
235
				$matches = $matches->getInterwikiResults();
236
				$hasInterwikiResults = true;
237
238
				// Include number of results if requested
239
				if ( $resultPageSet === null && isset( $searchInfo['totalhits'] ) ) {
240
					$totalhits += $matches->getTotalHits();
241
				}
242
243
				$result = $matches->next();
244
				while ( $result ) {
245
					$title = $result->getTitle();
246
247
					if ( $resultPageSet === null ) {
248
						$vals = [
249
							'namespace' => $result->getInterwikiNamespaceText(),
250
							'title' => $title->getText(),
251
							'url' => $title->getFullUrl(),
252
						];
253
254
						// Add item to results and see whether it fits
255
						$fit = $apiResult->addValue(
256
							[ 'query', 'interwiki' . $this->getModuleName(), $result->getInterwikiPrefix() ],
257
							null,
258
							$vals
259
						);
260
261
						if ( !$fit ) {
262
							// We hit the limit. We can't really provide any meaningful
263
							// pagination info so just bail out
264
							break;
265
						}
266
					} else {
267
						$titles[] = $title;
268
					}
269
270
					$result = $matches->next();
271
				}
272
			}
273
			if ( $totalhits !== null ) {
274
				$apiResult->addValue( [ 'query', 'interwikisearchinfo' ],
275
					'totalhits', $totalhits );
276
			}
277
		}
278
279
		if ( $resultPageSet === null ) {
280
			$apiResult->addIndexedTagName( [
281
				'query', $this->getModuleName()
282
			], 'p' );
283
			if ( $hasInterwikiResults ) {
284
				$apiResult->addIndexedTagName( [
285
					'query', 'interwiki' . $this->getModuleName()
286
				], 'p' );
287
			}
288
		} else {
289 View Code Duplication
			$resultPageSet->setRedirectMergePolicy( function ( $current, $new ) {
290
				if ( !isset( $current['index'] ) || $new['index'] < $current['index'] ) {
291
					$current['index'] = $new['index'];
292
				}
293
				return $current;
294
			} );
295
			$resultPageSet->populateFromTitles( $titles );
296
			$offset = $params['offset'] + 1;
297
			foreach ( $titles as $index => $title ) {
298
				$resultPageSet->setGeneratorData( $title, [ 'index' => $index + $offset ] );
299
			}
300
		}
301
	}
302
303
	public function getCacheMode( $params ) {
304
		return 'public';
305
	}
306
307
	public function getAllowedParams() {
308
		if ( $this->allowedParams !== null ) {
309
			return $this->allowedParams;
310
		}
311
312
		$this->allowedParams = [
313
			'search' => [
314
				ApiBase::PARAM_TYPE => 'string',
315
				ApiBase::PARAM_REQUIRED => true
316
			],
317
			'namespace' => [
318
				ApiBase::PARAM_DFLT => NS_MAIN,
319
				ApiBase::PARAM_TYPE => 'namespace',
320
				ApiBase::PARAM_ISMULTI => true,
321
			],
322
			'what' => [
323
				ApiBase::PARAM_TYPE => [
324
					'title',
325
					'text',
326
					'nearmatch',
327
				]
328
			],
329
			'info' => [
330
				ApiBase::PARAM_DFLT => 'totalhits|suggestion|rewrittenquery',
331
				ApiBase::PARAM_TYPE => [
332
					'totalhits',
333
					'suggestion',
334
					'rewrittenquery',
335
				],
336
				ApiBase::PARAM_ISMULTI => true,
337
			],
338
			'prop' => [
339
				ApiBase::PARAM_DFLT => 'size|wordcount|timestamp|snippet',
340
				ApiBase::PARAM_TYPE => [
341
					'size',
342
					'wordcount',
343
					'timestamp',
344
					'snippet',
345
					'titlesnippet',
346
					'redirecttitle',
347
					'redirectsnippet',
348
					'sectiontitle',
349
					'sectionsnippet',
350
					'isfilematch',
351
					'categorysnippet',
352
					'score', // deprecated
353
					'hasrelated', // deprecated
354
				],
355
				ApiBase::PARAM_ISMULTI => true,
356
				ApiBase::PARAM_HELP_MSG_PER_VALUE => [],
357
			],
358
			'offset' => [
359
				ApiBase::PARAM_DFLT => 0,
360
				ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
361
			],
362
			'limit' => [
363
				ApiBase::PARAM_DFLT => 10,
364
				ApiBase::PARAM_TYPE => 'limit',
365
				ApiBase::PARAM_MIN => 1,
366
				ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG1,
367
				ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2
368
			],
369
			'interwiki' => false,
370
			'enablerewrites' => false,
371
		];
372
373
		$searchConfig = MediaWikiServices::getInstance()->getSearchEngineConfig();
374
		$alternatives = $searchConfig->getSearchTypes();
375
		if ( count( $alternatives ) > 1 ) {
376
			if ( $alternatives[0] === null ) {
377
				$alternatives[0] = self::BACKEND_NULL_PARAM;
378
			}
379
			$this->allowedParams['backend'] = [
380
				ApiBase::PARAM_DFLT => $searchConfig->getSearchType(),
381
				ApiBase::PARAM_TYPE => $alternatives,
382
			];
383
			// @todo: support profile selection when multiple
384
			// backends are available. The solution could be to
385
			// merge all possible profiles and let ApiBase
386
			// subclasses do the check. Making ApiHelp and ApiSandbox
387
			// comprehensive might be more difficult.
388
		} else {
389
			$profileParam = $this->buildProfileApiParam( SearchEngine::FT_QUERY_INDEP_PROFILE_TYPE,
390
				'apihelp-query+search-param-qiprofile' );
391
			if ( $profileParam ) {
392
				$this->allowedParams['qiprofile'] = $profileParam;
393
			}
394
		}
395
396
		return $this->allowedParams;
397
	}
398
399
	public function getSearchProfileParams() {
400
		if ( isset( $this->getAllowedParams()['qiprofile'] ) ) {
401
			return [ SearchEngine::FT_QUERY_INDEP_PROFILE_TYPE => 'qiprofile' ];
402
		}
403
		return [];
404
	}
405
406
	protected function getExamplesMessages() {
407
		return [
408
			'action=query&list=search&srsearch=meaning'
409
				=> 'apihelp-query+search-example-simple',
410
			'action=query&list=search&srwhat=text&srsearch=meaning'
411
				=> 'apihelp-query+search-example-text',
412
			'action=query&generator=search&gsrsearch=meaning&prop=info'
413
				=> 'apihelp-query+search-example-generator',
414
		];
415
	}
416
417
	public function getHelpUrls() {
418
		return 'https://www.mediawiki.org/wiki/API:Search';
419
	}
420
}
421