Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 43 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
InterwikiSearcher | |
0.00% |
0 / 43 |
|
0.00% |
0 / 3 |
110 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
getInterwikiResults | |
0.00% |
0 / 39 |
|
0.00% |
0 / 1 |
72 | |||
recordQueryCacheMetrics | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace CirrusSearch; |
4 | |
5 | use CirrusSearch\Fallbacks\FallbackRunner; |
6 | use CirrusSearch\Parser\BasicQueryClassifier; |
7 | use CirrusSearch\Parser\NamespacePrefixParser; |
8 | use CirrusSearch\Search\CrossProjectBlockScorerFactory; |
9 | use CirrusSearch\Search\FullTextResultsType; |
10 | use CirrusSearch\Search\MSearchRequests; |
11 | use CirrusSearch\Search\SearchContext; |
12 | use CirrusSearch\Search\SearchQuery; |
13 | use CirrusSearch\Search\SearchQueryBuilder; |
14 | use CirrusSearch\Search\TitleHelper; |
15 | use MediaWiki\MediaWikiServices; |
16 | use MediaWiki\Status\Status; |
17 | use MediaWiki\User\User; |
18 | use Wikimedia\Stats\StatsFactory; |
19 | |
20 | /** |
21 | * Performs searches using Elasticsearch -- on interwikis! |
22 | * |
23 | * This program is free software; you can redistribute it and/or modify |
24 | * it under the terms of the GNU General Public License as published by |
25 | * the Free Software Foundation; either version 2 of the License, or |
26 | * (at your option) any later version. |
27 | * |
28 | * This program is distributed in the hope that it will be useful, |
29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
31 | * GNU General Public License for more details. |
32 | * |
33 | * You should have received a copy of the GNU General Public License along |
34 | * with this program; if not, write to the Free Software Foundation, Inc., |
35 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
36 | * http://www.gnu.org/copyleft/gpl.html |
37 | */ |
38 | class InterwikiSearcher extends Searcher { |
39 | |
40 | /** |
41 | * @param Connection $connection |
42 | * @param SearchConfig $config |
43 | * @param int[]|null $namespaces Namespace numbers to search, or null for all of them |
44 | * @param User|null $user |
45 | * @param CirrusDebugOptions|null $debugOptions |
46 | * @param NamespacePrefixParser|null $namespacePrefixParser |
47 | * @param InterwikiResolver|null $interwikiResolver |
48 | * @param TitleHelper|null $titleHelper |
49 | * @param CirrusSearchHookRunner|null $cirrusSearchHookRunner |
50 | */ |
51 | public function __construct( |
52 | Connection $connection, |
53 | SearchConfig $config, |
54 | ?array $namespaces = null, |
55 | ?User $user = null, |
56 | ?CirrusDebugOptions $debugOptions = null, |
57 | ?NamespacePrefixParser $namespacePrefixParser = null, |
58 | ?InterwikiResolver $interwikiResolver = null, |
59 | ?TitleHelper $titleHelper = null, |
60 | ?CirrusSearchHookRunner $cirrusSearchHookRunner = null |
61 | ) { |
62 | $maxResults = $config->get( 'CirrusSearchNumCrossProjectSearchResults' ); |
63 | parent::__construct( $connection, 0, $maxResults, $config, $namespaces, $user, false, |
64 | $debugOptions, $namespacePrefixParser, $interwikiResolver, $titleHelper, $cirrusSearchHookRunner ); |
65 | } |
66 | |
67 | /** |
68 | * Fetch search results, from caches, if there's any |
69 | * @param SearchQuery $query original search query |
70 | * @return Status |
71 | */ |
72 | public function getInterwikiResults( SearchQuery $query ): Status { |
73 | $sources = MediaWikiServices::getInstance() |
74 | ->getService( InterwikiResolver::SERVICE ) |
75 | ->getSisterProjectConfigs(); |
76 | if ( !$sources ) { |
77 | // Nothing to search for |
78 | return Status::newGood( [] ); |
79 | } |
80 | |
81 | $iwQueries = []; |
82 | foreach ( $sources as $interwiki => $config ) { |
83 | $iwQueries[$interwiki] = SearchQueryBuilder::forCrossProjectSearch( $config, $query ) |
84 | ->build(); |
85 | } |
86 | |
87 | $blockScorer = CrossProjectBlockScorerFactory::load( $this->config ); |
88 | $msearches = new MSearchRequests(); |
89 | foreach ( $iwQueries as $interwiki => $iwQuery ) { |
90 | $context = SearchContext::fromSearchQuery( $iwQuery, |
91 | FallbackRunner::create( $iwQuery, $this->interwikiResolver ), $this->cirrusSearchHookRunner ); |
92 | $this->searchContext = $context; |
93 | $this->setResultsType( new FullTextResultsType( |
94 | $this->searchContext->getFetchPhaseBuilder(), |
95 | $query->getParsedQuery()->isQueryOfClass( BasicQueryClassifier::COMPLEX_QUERY ), |
96 | $this->titleHelper, [], $this->searchContext->getConfig()->getElement( 'CirrusSearchDeduplicateInMemory' ) === true ) ); |
97 | $this->config = $context->getConfig(); |
98 | $this->limit = $iwQuery->getLimit(); |
99 | $this->offset = $iwQuery->getOffset(); |
100 | $this->buildFullTextSearch( $query->getParsedQuery()->getQueryWithoutNsHeader() ); |
101 | $this->indexBaseName = $context->getConfig()->get( 'CirrusSearchIndexBaseName' ); |
102 | $search = $this->buildSearch(); |
103 | if ( $this->searchContext->areResultsPossible() ) { |
104 | $msearches->addRequest( $interwiki, $search ); |
105 | } |
106 | } |
107 | |
108 | $searchDescription = "{$this->searchContext->getSearchType()} search for '{$this->searchContext->getOriginalSearchTerm()}'"; |
109 | if ( $this->searchContext->getDebugOptions()->isCirrusDumpQuery() ) { |
110 | return $msearches->dumpQuery( $searchDescription ); |
111 | } |
112 | $mresponses = $this->searchMulti( $msearches ); |
113 | if ( $mresponses->hasFailure() ) { |
114 | return $mresponses->getFailure(); |
115 | } |
116 | |
117 | if ( $this->searchContext->getDebugOptions()->isReturnRaw() ) { |
118 | return $mresponses->dumpResults( $searchDescription ); |
119 | } |
120 | |
121 | return $mresponses->transformAndGetMulti( $this->searchContext->getResultsType(), array_keys( $iwQueries ), |
122 | static function ( array $v ) use ( $blockScorer ) { |
123 | return $blockScorer->reorder( $v ); |
124 | } ); |
125 | } |
126 | |
127 | protected function recordQueryCacheMetrics( StatsFactory $requestStats, string $cacheStatus, ?string $type = null ): void { |
128 | parent::recordQueryCacheMetrics( $requestStats, $cacheStatus, "interwiki" ); |
129 | } |
130 | } |