Add ISearchResultSet

Bug: T228626
Change-Id: I3306bf6107c97dd58adf578fd965bd11a422627d
This commit is contained in:
David Causse 2019-07-22 17:28:48 +02:00 committed by EBernhardson
parent 9b30a0d77d
commit 6af636fb03
24 changed files with 218 additions and 86 deletions

View file

@ -659,6 +659,7 @@ $wgAutoloadLocalClasses = [
'IP' => __DIR__ . '/includes/libs/IP.php',
'IPTC' => __DIR__ . '/includes/media/IPTC.php',
'IRCColourfulRCFeedFormatter' => __DIR__ . '/includes/rcfeed/IRCColourfulRCFeedFormatter.php',
'ISearchResultSet' => __DIR__ . '/includes/search/ISearchResultSet.php',
'IStoreKeyEncoder' => __DIR__ . '/includes/libs/objectcache/IStoreKeyEncoder.php',
'IcuCollation' => __DIR__ . '/includes/collation/IcuCollation.php',
'IdentityCollation' => __DIR__ . '/includes/collation/IdentityCollation.php',

View file

@ -3304,8 +3304,8 @@ $opts: Array: key => value of hidden options for inclusion in custom forms
'SpecialSearchResults': Called before search result display
$term: string of search term
&$titleMatches: empty or SearchResultSet object
&$textMatches: empty or SearchResultSet object
&$titleMatches: empty or ISearchResultSet object
&$textMatches: empty or ISearchResultSet object
'SpecialSearchResultsPrepend': Called immediately before returning HTML
on the search results page. Useful for including an external search

View file

@ -180,13 +180,13 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
$canAddInterwiki = (bool)$params['enablerewrites'] && ( $resultPageSet === null );
if ( $canAddInterwiki ) {
$this->addInterwikiResults( $matches, $apiResult, $prop, 'additional',
SearchResultSet::INLINE_RESULTS );
ISearchResultSet::INLINE_RESULTS );
}
// Interwiki results outside main result set
if ( $interwiki && $resultPageSet === null ) {
$this->addInterwikiResults( $matches, $apiResult, $prop, 'interwiki',
SearchResultSet::SECONDARY_RESULTS );
ISearchResultSet::SECONDARY_RESULTS );
}
if ( $resultPageSet === null ) {
@ -278,7 +278,7 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
/**
* Add interwiki results as a section in query results.
* @param SearchResultSet $matches
* @param ISearchResultSet $matches
* @param ApiResult $apiResult
* @param array $prop Props to extract (as keys)
* @param string $section Section name where results would go
@ -286,7 +286,7 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
* @return int|null Number of total hits in the data or null if none was produced
*/
private function addInterwikiResults(
SearchResultSet $matches, ApiResult $apiResult, $prop,
ISearchResultSet $matches, ApiResult $apiResult, $prop,
$section, $type
) {
$totalhits = null;

View file

@ -13,7 +13,7 @@ class AugmentPageProps implements ResultSetAugmentor {
$this->propnames = $propnames;
}
public function augmentAll( SearchResultSet $resultSet ) {
public function augmentAll( ISearchResultSet $resultSet ) {
$titles = $resultSet->extractTitles();
return PageProps::getInstance()->getProperties( $titles, $this->propnames );
}

View file

@ -0,0 +1,142 @@
<?php
/**
* @ingroup Search
*/
interface ISearchResultSet extends \Countable, \IteratorAggregate {
/**
* Identifier for interwiki results that are displayed only together with existing main wiki
* results.
*/
const SECONDARY_RESULTS = 0;
/**
* Identifier for interwiki results that can be displayed even if no existing main wiki results
* exist.
*/
const INLINE_RESULTS = 1;
/**
* @return int
*/
function numRows();
/**
* Some search modes return a total hit count for the query
* in the entire article database. This may include pages
* in namespaces that would not be matched on the given
* settings.
*
* Return null if no total hits number is supported.
*
* @return int|null
*/
function getTotalHits();
/**
* Some search modes will run an alternative query that it thinks gives
* a better result than the provided search. Returns true if this has
* occurred.
*
* @return bool
*/
function hasRewrittenQuery();
/**
* @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 string|null Same as self::getQueryAfterRewrite(), but in HTML
* and with changes highlighted. Null when the query was not rewritten.
*/
function getQueryAfterRewriteSnippet();
/**
* Some search modes return a suggested alternate term if there are
* no exact hits. Returns true if there is one on this set.
*
* @return bool
*/
function hasSuggestion();
/**
* @return string|null Suggested query, null if none
*/
function getSuggestionQuery();
/**
* @return string HTML highlighted suggested query, '' if none
*/
function getSuggestionSnippet();
/**
* Return a result set of hits on other (multiple) wikis associated with this one
*
* @param int $type
* @return ISearchResultSet[]
*/
function getInterwikiResults( $type = self::SECONDARY_RESULTS );
/**
* Check if there are results on other wikis
*
* @param int $type
* @return bool
*/
function hasInterwikiResults( $type = self::SECONDARY_RESULTS );
/**
* Did the search contain search syntax? If so, Special:Search won't offer
* the user a link to a create a page named by the search string because the
* name would contain the search syntax.
* @return bool
*/
public function searchContainedSyntax();
/**
* @return bool True when there are more pages of search results available.
*/
public function hasMoreResults();
/**
* @param int $limit Shrink result set to $limit and flag
* if more results are available.
*/
public function shrink( $limit );
/**
* Extract all the results in the result set as array.
* @return SearchResult[]
*/
public function extractResults();
/**
* Extract all the titles in the result set.
* @return Title[]
*/
public function extractTitles();
/**
* Sets augmented data for result set.
* @param string $name Extra data item name
* @param array[] $data Extra data as PAGEID => data
*/
public function setAugmentedData( $name, $data );
/**
* Returns extra data for specific result and store it in SearchResult object.
* @param SearchResult $result
*/
public function augmentResult( SearchResult $result );
/**
* @return int|null The offset the current page starts at. Typically
* this should be null to allow the UI to decide on its own, but in
* special cases like interleaved AB tests specifying explicitly is
* necessary.
*/
public function getOffset();
}

View file

@ -2,7 +2,7 @@
/**
* Marker class for search engines that can handle their own pagination, by
* reporting in their SearchResultSet when a next page is available. This
* reporting in their ISearchResultSet when a next page is available. This
* only applies to search{Title,Text} and not to completion search.
*
* SearchEngine implementations not implementing this interface will have

View file

@ -20,10 +20,10 @@ class PerRowAugmentor implements ResultSetAugmentor {
/**
* Produce data to augment search result set.
* @param SearchResultSet $resultSet
* @param ISearchResultSet $resultSet
* @return array Data for all results
*/
public function augmentAll( SearchResultSet $resultSet ) {
public function augmentAll( ISearchResultSet $resultSet ) {
$data = [];
foreach ( $resultSet->extractResults() as $result ) {
$id = $result->getTitle()->getArticleID();

View file

@ -6,8 +6,8 @@
interface ResultSetAugmentor {
/**
* Produce data to augment search result set.
* @param SearchResultSet $resultSet
* @param ISearchResultSet $resultSet
* @return array Data for all results
*/
public function augmentAll( SearchResultSet $resultSet );
public function augmentAll( ISearchResultSet $resultSet );
}

View file

@ -51,7 +51,7 @@ abstract class SearchDatabase extends SearchEngine {
/**
* @param string $term
* @return SearchResultSet|Status|null
* @return ISearchResultSet|Status|null
*/
final public function doSearchText( $term ) {
return $this->doSearchTextInDB( $this->extractNamespacePrefix( $term ) );
@ -67,7 +67,7 @@ abstract class SearchDatabase extends SearchEngine {
/**
* @param string $term
* @return SearchResultSet|null
* @return ISearchResultSet|null
*/
final public function doSearchTitle( $term ) {
return $this->doSearchTitleInDB( $this->extractNamespacePrefix( $term ) );

View file

@ -79,7 +79,7 @@ abstract class SearchEngine {
* be converted to final in 1.34. Override self::doSearchText().
*
* @param string $term Raw search term
* @return SearchResultSet|Status|null
* @return ISearchResultSet|Status|null
*/
public function searchText( $term ) {
return $this->maybePaginate( function () use ( $term ) {
@ -91,7 +91,7 @@ abstract class SearchEngine {
* Perform a full text search query and return a result set.
*
* @param string $term Raw search term
* @return SearchResultSet|Status|null
* @return ISearchResultSet|Status|null
* @since 1.32
*/
protected function doSearchText( $term ) {
@ -136,7 +136,7 @@ abstract class SearchEngine {
* be converted to final in 1.34. Override self::doSearchTitle().
*
* @param string $term Raw search term
* @return SearchResultSet|null
* @return ISearchResultSet|null
*/
public function searchTitle( $term ) {
return $this->maybePaginate( function () use ( $term ) {
@ -148,7 +148,7 @@ abstract class SearchEngine {
* Perform a title-only search query and return a result set.
*
* @param string $term Raw search term
* @return SearchResultSet|null
* @return ISearchResultSet|null
* @since 1.32
*/
protected function doSearchTitle( $term ) {
@ -161,7 +161,7 @@ abstract class SearchEngine {
* explicitly implement their own pagination.
*
* @param Closure $fn Takes no arguments
* @return SearchResultSet|Status<SearchResultSet>|null Result of calling $fn
* @return ISearchResultSet|Status<ISearchResultSet>|null Result of calling $fn
*/
private function maybePaginate( Closure $fn ) {
if ( $this instanceof PaginatingSearchEngine ) {
@ -175,10 +175,10 @@ abstract class SearchEngine {
}
$resultSet = null;
if ( $resultSetOrStatus instanceof SearchResultSet ) {
if ( $resultSetOrStatus instanceof ISearchResultSet ) {
$resultSet = $resultSetOrStatus;
} elseif ( $resultSetOrStatus instanceof Status &&
$resultSetOrStatus->getValue() instanceof SearchResultSet
$resultSetOrStatus->getValue() instanceof ISearchResultSet
) {
$resultSet = $resultSetOrStatus->getValue();
}
@ -784,9 +784,9 @@ abstract class SearchEngine {
/**
* Augment search results with extra data.
*
* @param SearchResultSet $resultSet
* @param ISearchResultSet $resultSet
*/
public function augmentSearchResults( SearchResultSet $resultSet ) {
public function augmentSearchResults( ISearchResultSet $resultSet ) {
$setAugmentors = [];
$rowAugmentors = [];
Hooks::run( "SearchResultsAugment", [ &$setAugmentors, &$rowAugmentors ] );

View file

@ -1,6 +1,6 @@
<?php
/**
* A SearchResultSet wrapper for SearchNearMatcher
* A ISearchResultSet wrapper for SearchNearMatcher
*/
class SearchNearMatchResultSet extends SearchResultSet {
/**

View file

@ -39,10 +39,10 @@ class SearchNearMatcher {
/**
* Do a near match (see SearchEngine::getNearMatch) and wrap it into a
* SearchResultSet.
* ISearchResultSet.
*
* @param string $searchterm
* @return SearchResultSet
* @return ISearchResultSet
*/
public function getNearMatchResultSet( $searchterm ) {
return new SearchNearMatchResultSet( $this->getNearMatch( $searchterm ) );

View file

@ -66,10 +66,10 @@ class SearchResult {
* Return a new SearchResult and initializes it with a title.
*
* @param Title $title
* @param SearchResultSet|null $parentSet
* @param ISearchResultSet|null $parentSet
* @return SearchResult
*/
public static function newFromTitle( $title, SearchResultSet $parentSet = null ) {
public static function newFromTitle( $title, ISearchResultSet $parentSet = null ) {
$result = new static();
$result->initFromTitle( $title );
if ( $parentSet ) {

View file

@ -24,19 +24,7 @@
/**
* @ingroup Search
*/
class SearchResultSet implements Countable, IteratorAggregate {
/**
* Identifier for interwiki results that are displayed only together with existing main wiki
* results.
*/
const SECONDARY_RESULTS = 0;
/**
* Identifier for interwiki results that can be displayed even if no existing main wiki results
* exist.
*/
const INLINE_RESULTS = 1;
class SearchResultSet implements ISearchResultSet {
protected $containedSyntax = false;
@ -179,7 +167,7 @@ class SearchResultSet implements Countable, IteratorAggregate {
* Return a result set of hits on other (multiple) wikis associated with this one
*
* @param int $type
* @return SearchResultSet[]
* @return ISearchResultSet[]
*/
function getInterwikiResults( $type = self::SECONDARY_RESULTS ) {
return null;

View file

@ -377,9 +377,9 @@ class SpecialSearch extends SpecialPage {
$hasErrors = $textStatus && $textStatus->getErrors() !== [];
$hasOtherResults = $textMatches &&
$textMatches->hasInterwikiResults( SearchResultSet::INLINE_RESULTS );
$textMatches->hasInterwikiResults( ISearchResultSet::INLINE_RESULTS );
if ( $textMatches && $textMatches->hasInterwikiResults( SearchResultSet::SECONDARY_RESULTS ) ) {
if ( $textMatches && $textMatches->hasInterwikiResults( ISearchResultSet::SECONDARY_RESULTS ) ) {
$out->addHTML( '<div class="searchresults mw-searchresults-has-iw">' );
} else {
$out->addHTML( '<div class="searchresults">' );
@ -473,8 +473,8 @@ class SpecialSearch extends SpecialPage {
/**
* @param Title $title
* @param int $num The number of search results found
* @param null|SearchResultSet $titleMatches Results from title search
* @param null|SearchResultSet $textMatches Results from text search
* @param null|ISearchResultSet $titleMatches Results from title search
* @param null|ISearchResultSet $textMatches Results from text search
*/
protected function showCreateLink( $title, $num, $titleMatches, $textMatches ) {
// show direct page/create link if applicable

View file

@ -2,9 +2,9 @@
namespace MediaWiki\Widget\Search;
use ISearchResultSet;
use MediaWiki\MediaWikiServices;
use Message;
use SearchResultSet;
use SpecialSearch;
use Status;
@ -33,23 +33,23 @@ class BasicSearchResultSetWidget {
/**
* @param string $term The search term to highlight
* @param int $offset The offset of the first result in the result set
* @param SearchResultSet|null $titleResultSet Results of searching only page titles
* @param SearchResultSet|null $textResultSet Results of general full text search.
* @param ISearchResultSet|null $titleResultSet Results of searching only page titles
* @param ISearchResultSet|null $textResultSet Results of general full text search.
* @return string HTML
*/
public function render(
$term,
$offset,
SearchResultSet $titleResultSet = null,
SearchResultSet $textResultSet = null
ISearchResultSet $titleResultSet = null,
ISearchResultSet $textResultSet = null
) {
$hasTitle = $titleResultSet ? $titleResultSet->numRows() > 0 : false;
$hasText = $textResultSet ? $textResultSet->numRows() > 0 : false;
$hasSecondary = $textResultSet
? $textResultSet->hasInterwikiResults( SearchResultSet::SECONDARY_RESULTS )
? $textResultSet->hasInterwikiResults( ISearchResultSet::SECONDARY_RESULTS )
: false;
$hasSecondaryInline = $textResultSet
? $textResultSet->hasInterwikiResults( SearchResultSet::INLINE_RESULTS )
? $textResultSet->hasInterwikiResults( ISearchResultSet::INLINE_RESULTS )
: false;
if ( !$hasTitle && !$hasText && !$hasSecondary && !$hasSecondaryInline ) {
@ -71,7 +71,7 @@ class BasicSearchResultSetWidget {
}
if ( $hasSecondaryInline ) {
$iwResults = $textResultSet->getInterwikiResults( SearchResultSet::INLINE_RESULTS );
$iwResults = $textResultSet->getInterwikiResults( ISearchResultSet::INLINE_RESULTS );
foreach ( $iwResults as $interwiki => $results ) {
if ( $results instanceof Status || $results->numRows() === 0 ) {
// ignore bad interwikis for now
@ -88,7 +88,7 @@ class BasicSearchResultSetWidget {
if ( $hasSecondary ) {
$out .= $this->sidebarWidget->render(
$term,
$textResultSet->getInterwikiResults( SearchResultSet::SECONDARY_RESULTS )
$textResultSet->getInterwikiResults( ISearchResultSet::SECONDARY_RESULTS )
);
}
@ -112,11 +112,11 @@ class BasicSearchResultSetWidget {
}
/**
* @param SearchResultSet $resultSet The search results to render
* @param ISearchResultSet $resultSet The search results to render
* @param int $offset Offset of the first result in $resultSet
* @return string HTML
*/
protected function renderResultSet( SearchResultSet $resultSet, $offset ) {
protected function renderResultSet( ISearchResultSet $resultSet, $offset ) {
$hits = [];
foreach ( $resultSet as $result ) {
$hits[] = $this->resultWidget->render( $result, $offset++ );

View file

@ -3,7 +3,7 @@
namespace MediaWiki\Widget\Search;
use HtmlArmor;
use SearchResultSet;
use ISearchResultSet;
use SpecialSearch;
/**
@ -20,10 +20,10 @@ class DidYouMeanWidget {
/**
* @param string $term The user provided search term
* @param SearchResultSet $resultSet
* @param ISearchResultSet $resultSet
* @return string HTML
*/
public function render( $term, SearchResultSet $resultSet ) {
public function render( $term, ISearchResultSet $resultSet ) {
if ( $resultSet->hasRewrittenQuery() ) {
$html = $this->rewrittenHtml( $term, $resultSet );
} elseif ( $resultSet->hasSuggestion() ) {
@ -40,11 +40,11 @@ class DidYouMeanWidget {
* rewritten, and the results of the rewritten query are being returned.
*
* @param string $term The users search input
* @param SearchResultSet $resultSet The response to the search request
* @param ISearchResultSet $resultSet The response to the search request
* @return string HTML Links the user to their original $term query, and the
* one suggested by $resultSet
*/
protected function rewrittenHtml( $term, SearchResultSet $resultSet ) {
protected function rewrittenHtml( $term, ISearchResultSet $resultSet ) {
$params = [
'search' => $resultSet->getQueryAfterRewrite(),
// Don't magic this link into a 'go' link, it should always
@ -81,10 +81,10 @@ class DidYouMeanWidget {
* a query that might give more/better results than their current
* query.
*
* @param SearchResultSet $resultSet
* @param ISearchResultSet $resultSet
* @return string HTML
*/
protected function suggestionHtml( SearchResultSet $resultSet ) {
protected function suggestionHtml( ISearchResultSet $resultSet ) {
$params = [
'search' => $resultSet->getSuggestionQuery(),
'fulltext' => 1,

View file

@ -4,14 +4,14 @@ namespace MediaWiki\Widget\Search;
use MediaWiki\Interwiki\InterwikiLookup;
use MediaWiki\Linker\LinkRenderer;
use SearchResultSet;
use ISearchResultSet;
use SpecialSearch;
use Title;
use Html;
use OOUI;
/**
* Renders one or more SearchResultSets into a sidebar grouped by
* Renders one or more ISearchResultSets into a sidebar grouped by
* interwiki prefix. Includes a per-wiki header indicating where
* the results are from.
*/
@ -48,7 +48,7 @@ class InterwikiSearchResultSetWidget implements SearchResultSetWidget {
/**
* @param string $term User provided search term
* @param SearchResultSet|SearchResultSet[] $resultSets List of interwiki
* @param ISearchResultSet|ISearchResultSet[] $resultSets List of interwiki
* results to render.
* @return string HTML
*/

View file

@ -2,7 +2,7 @@
namespace MediaWiki\Widget\Search;
use SearchResultSet;
use ISearchResultSet;
/**
* Renders a set of search results to HTML
@ -10,7 +10,7 @@ use SearchResultSet;
interface SearchResultSetWidget {
/**
* @param string $term User provided search term
* @param SearchResultSet|SearchResultSet[] $resultSets List of interwiki
* @param ISearchResultSet|ISearchResultSet[] $resultSets List of interwiki
* results to render.
* @return string HTML
*/

View file

@ -4,13 +4,13 @@ namespace MediaWiki\Widget\Search;
use MediaWiki\Interwiki\InterwikiLookup;
use MediaWiki\Linker\LinkRenderer;
use SearchResultSet;
use ISearchResultSet;
use SpecialSearch;
use Title;
use Html;
/**
* Renders one or more SearchResultSets into a sidebar grouped by
* Renders one or more ISearchResultSets into a sidebar grouped by
* interwiki prefix. Includes a per-wiki header indicating where
* the results are from.
*
@ -43,7 +43,7 @@ class SimpleSearchResultSetWidget implements SearchResultSetWidget {
/**
* @param string $term User provided search term
* @param SearchResultSet|SearchResultSet[] $resultSets List of interwiki
* @param ISearchResultSet|ISearchResultSet[] $resultSets List of interwiki
* results to render.
* @return string HTML
*/

View file

@ -54,7 +54,7 @@ class ApiQuerySearchTest extends ApiTestCase {
'one wiki response' => [
[ 'utwiki' => [ 'Qwerty' ] ],
[
SearchResultSet::SECONDARY_RESULTS => [
ISearchResultSet::SECONDARY_RESULTS => [
'utwiki' => new MockSearchResultSet( [
$this->mockResultClosure(
'Qwerty',

View file

@ -38,7 +38,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
'wgCapitalLinks' => true,
'wgCapitalLinkOverrides' => [
NS_CATEGORY => false // for testCompletionSearchMustRespectCapitalLinkOverrides
]
],
] );
$lb = LoadBalancerSingle::newFromConnection( $this->db );
@ -64,7 +64,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
'wgCapitalLinks' => true,
'wgCapitalLinkOverrides' => [
NS_CATEGORY => false // for testCompletionSearchMustRespectCapitalLinkOverrides
]
],
] );
$this->insertPage( 'Not_Main_Page', 'This is not a main page' );
@ -283,7 +283,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
$mockField =
$this->getMockBuilder( SearchIndexFieldDefinition::class )->setConstructorArgs( [
$name,
$type
$type,
] )->getMock();
$mockField->expects( $this->any() )->method( 'getMapping' )->willReturn( [
@ -346,8 +346,9 @@ class SearchEngineTest extends MediaWikiLangTestCase {
$setAugmentor = $this->createMock( ResultSetAugmentor::class );
$setAugmentor->expects( $this->once() )
->method( 'augmentAll' )
->willReturnCallback( function ( SearchResultSet $resultSet ) {
->willReturnCallback( function ( ISearchResultSet $resultSet ) {
$data = [];
/** @var SearchResult $result */
foreach ( $resultSet as $result ) {
$id = $result->getTitle()->getArticleID();
$data[$id] = "Result:$id:" . $result->getTitle()->getText();
@ -405,7 +406,7 @@ class SearchEngineTest extends MediaWikiLangTestCase {
[
'query' => 'foo',
],
false
false,
],
'empty' => [
[
@ -445,34 +446,34 @@ class SearchEngineTest extends MediaWikiLangTestCase {
'query' => 'all:test',
'withAll' => false,
],
false
false,
],
'ns only' => [
[
'query' => 'help:',
],
[ '', [ NS_HELP ] ]
[ '', [ NS_HELP ] ],
],
'all only' => [
[
'query' => 'all:',
'withAll' => true,
],
[ '', null ]
[ '', null ],
],
'all wins over namespace when first' => [
[
'query' => 'all:help:test',
'withAll' => true,
],
[ 'help:test', null ]
[ 'help:test', null ],
],
'ns wins over all when first' => [
[
'query' => 'help:all:test',
'withAll' => true,
],
[ 'all:test', [ NS_HELP ] ]
[ 'all:test', [ NS_HELP ] ],
],
];
}

View file

@ -5,7 +5,7 @@ use MediaWiki\MediaWikiServices;
class MockSearchEngine extends SearchEngine {
/** @var SearchResult[][] */
private static $results = [];
/** @var SearchResultSet[][] */
/** @var ISearchResultSet[][] */
private static $interwikiResults = [];
public static function clearMockResults() {
@ -33,7 +33,7 @@ class MockSearchEngine extends SearchEngine {
}
/**
* @param SearchResultSet[][] $interwikiResults
* @param ISearchResultSet[][] $interwikiResults
*/
public static function setMockInterwikiResults( array $interwikiResults ) {
self::$interwikiResults = $interwikiResults;

View file

@ -9,7 +9,7 @@ class MockSearchResultSet extends SearchResultSet {
/**
* @param SearchResult[]|callable[] $results
* @param SearchResultSet[][]|callable[][] $interwikiResults Map from result type
* @param ISearchResultSet[][]|callable[][] $interwikiResults Map from result type
* to list of results for that type.
*/
public function __construct( array $results, array $interwikiResults = [] ) {