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 );
$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
)
),
'info' => array(
- ApiBase::PARAM_DFLT => 'totalhits|suggestion',
+ ApiBase::PARAM_DFLT => 'totalhits|suggestion|rewrittenquery',
ApiBase::PARAM_TYPE => array(
'totalhits',
'suggestion',
+ 'rewrittenquery',
),
ApiBase::PARAM_ISMULTI => true,
),
ApiBase::PARAM_MAX2 => ApiBase::LIMIT_SML2
),
'interwiki' => false,
+ 'enablerewrites' => false,
);
$alternatives = SearchEngine::getSearchTypes();
"apihelp-query+search-param-limit": "How many total pages to return.",
"apihelp-query+search-param-interwiki": "Include interwiki results in the search, if available.",
"apihelp-query+search-param-backend": "Which search backend to use, if not the default.",
+ "apihelp-query+search-param-enablerewrites": "Enable internal query rewriting. Some search backends can rewrite the query into one its thinks gives better results, such as correcting spelling errors.",
"apihelp-query+search-example-simple": "Search for <kbd>meaning</kbd>.",
"apihelp-query+search-example-text": "Search texts for <kbd>meaning</kbd>.",
"apihelp-query+search-example-generator": "Get page info about the pages returned for a search for <kbd>meaning</kbd>.",
"apihelp-query+search-param-limit": "{{doc-apihelp-param|query+search|limit}}",
"apihelp-query+search-param-interwiki": "{{doc-apihelp-param|query+search|interwiki}}",
"apihelp-query+search-param-backend": "{{doc-apihelp-param|query+search|backend}}",
+ "apihelp-query+search-param-enablerewrites": "{{doc-apihelp-param|query+search|enablerewrites}}",
"apihelp-query+search-example-simple": "{{doc-apihelp-example|query+search}}",
"apihelp-query+search-example-text": "{{doc-apihelp-example|query+search}}",
"apihelp-query+search-example-generator": "{{doc-apihelp-example|query+search}}",
return null;
}
+ /**
+ * Some search modes will run an alternative query that it thinks gives
+ * a better result than the provided search. Returns true if this has
+ * occured.
+ *
+ * @return bool
+ */
+ function hasRewrittenQuery() {
+ return false;
+ }
+
+ /**
+ * @return string|null The search the query was internally rewritten to,
+ * or null when the result of the original query was returned.
+ */
+ function getQueryAfterRewrite() {
+ return null;
+ }
+
+ /**
+ * @return string|null Same as self::getQueryAfterRewrite(), but in HTML
+ * and with changes highlighted. Null when the query was not rewritten.
+ */
+ function getQueryAfterRewriteSnippet() {
+ return null;
+ }
+
/**
* Some search modes return a suggested alternate term if there are
* no exact hits. Returns true if there is one on this set.
global $wgContLang;
$search = $this->getSearchEngine();
+ $search->setFeatureData( 'rewrite', $this->runSuggestion );
$search->setLimitOffset( $this->limit, $this->offset );
$search->setNamespaces( $this->namespaces );
$search->prefix = $this->mPrefix;
// did you mean... suggestions
$didYouMeanHtml = '';
if ( $showSuggestion && $textMatches && !$textStatus ) {
- if ( $this->shouldRunSuggestedQuery( $textMatches ) ) {
- $newMatches = $search->searchText( $textMatches->getSuggestionQuery() );
- if ( $newMatches instanceof SearchResultSet && $newMatches->numRows() > 0 ) {
- $didYouMeanHtml = $this->getDidYouMeanRewrittenHtml( $term, $textMatches );
- $textMatches = $newMatches;
- }
+ if ( $textMatches->hasRewrittenQuery() ) {
+ $didYouMeanHtml = $this->getDidYouMeanRewrittenHtml( $term, $textMatches );
} elseif ( $textMatches->hasSuggestion() ) {
$didYouMeanHtml = $this->getDidYouMeanHtml( $textMatches );
}
// Showing results for '$rewritten'
// Search instead for '$orig'
- $params = array( 'search' => $textMatches->getSuggestionQuery() );
+ $params = array( 'search' => $textMatches->getQueryAfterRewrite() );
if ( $this->fulltext != null ) {
$params['fulltext'] = $this->fulltext;
}
$rewritten = Linker::linkKnown(
$this->getPageTitle(),
- $textMatches->getSuggestionSnippet() ?: null,
+ $textMatches->getQueryAfterRewriteSnippet() ?: null,
array(),
$stParams
);
public function provideRewriteQueryWithSuggestion() {
return array(
array(
- 'With results and a suggestion does not run suggested query',
+ 'With suggestion and no rewritten query shows did you mean',
'/Did you mean: <a[^>]+>first suggestion/',
- array(
- new SpecialSearchTestMockResultSet( 'first suggestion', array(
- SearchResult::newFromTitle( Title::newMainPage() ),
- ) ),
- new SpecialSearchTestMockResultSet( 'was never run', array() ),
- ),
+ new SpecialSearchTestMockResultSet( 'first suggestion', null, array(
+ SearchResult::newFromTitle( Title::newMainPage() ),
+ ) ),
),
array(
- 'With no results and a suggestion responds with suggested query results',
+ 'With rewritten query informs user of change',
'/Showing results for <a[^>]+>first suggestion/',
- array(
- new SpecialSearchTestMockResultSet( 'first suggestion', array() ),
- new SpecialSearchTestMockResultSet( 'second suggestion', array(
- SearchResult::newFromTitle( Title::newMainPage() ),
- ) ),
- ),
+ new SpecialSearchTestMockResultSet( 'asdf', 'first suggestion', array(
+ SearchResult::newFromTitle( Title::newMainPage() ),
+ ) ),
),
array(
'When both queries have no results user gets no results',
'/There were no results matching the query/',
- array(
- new SpecialSearchTestMockResultSet( 'first suggestion', array() ),
- new SpecialSearchTestMockResultSet( 'second suggestion', array() ),
- ),
+ new SpecialSearchTestMockResultSet( 'first suggestion', 'first suggestion', array() ),
),
);
}
/**
* @dataProvider provideRewriteQueryWithSuggestion
*/
- public function testRewriteQueryWithSuggestion( $message, $expectRegex, $fromResults ) {
- $mockSearchEngine = $this->mockSearchEngine( $fromResults );
+ public function testRewriteQueryWithSuggestion( $message, $expectRegex, $results ) {
+ $mockSearchEngine = $this->mockSearchEngine( $results );
$search = $this->getMockBuilder( 'SpecialSearch' )
->setMethods( array( 'getSearchEngine' ) )
->getMock();
}
}
- protected function mockSearchEngine( array $returnValues ) {
+ protected function mockSearchEngine( $results ) {
$mock = $this->getMockBuilder( 'SearchEngine' )
- ->setMethods( array( 'searchText' ) )
+ ->setMethods( array( 'searchText', 'searchTitle' ) )
->getMock();
$mock->expects( $this->any() )
->method( 'searchText' )
- ->will( call_user_func_array(
- array( $this, 'onConsecutiveCalls' ),
- array_map( array( $this, 'returnValue' ), $returnValues )
- ) );
+ ->will( $this->returnValue( $results ) );
return $mock;
}
protected $results;
protected $suggestion;
- public function __construct( $suggestion = null, array $results = array(), $containedSyntax = false) {
- $this->results = $results;
+ public function __construct( $suggestion = null, $rewrittenQuery = null, array $results = array(), $containedSyntax = false) {
$this->suggestion = $suggestion;
+ $this->rewrittenQuery = $rewrittenQuery;
+ $this->results = $results;
$this->containedSyntax = $containedSyntax;
}
public function getSuggestionSnippet() {
return $this->suggestion;
}
+
+ public function hasRewrittenQuery() {
+ return $this->rewrittenQuery !== null;
+ }
+
+ public function getQueryAfterRewrite() {
+ return $this->rewrittenQuery;
+ }
+
+ public function getQueryAfterRewriteSnippet() {
+ return htmlspecialchars( $this->rewrittenQuery );
+ }
}