Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 24
CRAP
0.00% covered (danger)
0.00%
0 / 1
InterleavedResultSet
0.00% covered (danger)
0.00%
0 / 35
0.00% covered (danger)
0.00%
0 / 24
650
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
2
 getMetrics
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 getOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 extractResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getElasticResponse
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getElasticaResultSet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 addInterwikiResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setRewrittenQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 count
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 numRows
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTotalHits
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasRewrittenQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryAfterRewrite
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryAfterRewriteSnippet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasSuggestion
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSuggestionQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getSuggestionSnippet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getInterwikiResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasInterwikiResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 searchContainedSyntax
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasMoreResults
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 shrink
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 extractTitles
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setSuggestionQuery
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace CirrusSearch\Search;
4
5use BaseSearchResultSet;
6use Elastica\Response;
7use HtmlArmor;
8use ISearchResultSet;
9use MediaWiki\Title\Title;
10use SearchResultSetTrait;
11
12class InterleavedResultSet extends BaseSearchResultSet implements CirrusSearchResultSet, SearchMetricsProvider {
13    use SearchResultSetTrait;
14
15    /** @var string[] Doc ID's belonging to team A */
16    private $teamA;
17    /** @var string[] Doc ID's belonging to team B */
18    private $teamB;
19    /** @var int Offset to calculate next unused result in team A */
20    private $offset;
21    /** @var CirrusSearchResultSet */
22    private $delegate;
23    /** @var CirrusSearchResult[] */
24    private $results;
25
26    /**
27     * @param CirrusSearchResultSet $nested Original result set for team A (control)
28     * @param CirrusSearchResult[] $interleaved Interleaved results
29     * @param string[] $teamA Document id's belonging to team A
30     * @param string[] $teamB Document id's belonging to team B
31     * @param int $offset Offset to calculate next unused result in team A
32     */
33    public function __construct(
34        CirrusSearchResultSet $nested,
35        array $interleaved,
36        array $teamA,
37        array $teamB,
38        $offset
39    ) {
40        $this->results = $interleaved;
41        $this->teamA = $teamA;
42        $this->teamB = $teamB;
43        $this->offset = $offset;
44        $this->delegate = $nested;
45    }
46
47    public function getMetrics() {
48        return [
49            'wgCirrusSearchTeamDraft' => [
50                'a' => $this->teamA,
51                'b' => $this->teamB,
52            ],
53        ];
54    }
55
56    /**
57     * @return int|null
58     */
59    public function getOffset() {
60        return $this->offset;
61    }
62
63    /**
64     * @return CirrusSearchResult[]
65     */
66    public function extractResults() {
67        return $this->results;
68    }
69
70    /**
71     * @return Response|null
72     */
73    public function getElasticResponse() {
74        return $this->delegate->getElasticResponse();
75    }
76
77    /**
78     * @return \Elastica\ResultSet|null
79     */
80    public function getElasticaResultSet() {
81        return $this->delegate->getElasticaResultSet();
82    }
83
84    /**
85     * @param CirrusSearchResultSet $res
86     * @param int $type one of searchresultset::* constants
87     * @param string $interwiki
88     */
89    public function addInterwikiResults( CirrusSearchResultSet $res, $type, $interwiki ) {
90        $this->delegate->addInterwikiResults( $res, $type, $interwiki );
91    }
92
93    /**
94     * @param string $newQuery
95     * @param HtmlArmor|string|null $newQuerySnippet
96     */
97    public function setRewrittenQuery( string $newQuery, $newQuerySnippet = null ) {
98        $this->delegate->setRewrittenQuery( $newQuery, $newQuerySnippet );
99    }
100
101    /**
102     * Count elements of an object
103     * @link https://php.net/manual/en/countable.count.php
104     * @return int The custom count as integer.
105     * @since 5.1.0
106     */
107    public function count(): int {
108        return count( $this->results );
109    }
110
111    /**
112     * @return int
113     */
114    public function numRows() {
115        return $this->count();
116    }
117
118    /**
119     * Some search modes return a total hit count for the query
120     * in the entire article database. This may include pages
121     * in namespaces that would not be matched on the given
122     * settings.
123     *
124     * Return null if no total hits number is supported.
125     *
126     * @return int|null
127     */
128    public function getTotalHits() {
129        return $this->delegate->getTotalHits();
130    }
131
132    /**
133     * Some search modes will run an alternative query that it thinks gives
134     * a better result than the provided search. Returns true if this has
135     * occurred.
136     *
137     * @return bool
138     */
139    public function hasRewrittenQuery() {
140        return $this->delegate->hasRewrittenQuery();
141    }
142
143    /**
144     * @return string|null The search the query was internally rewritten to,
145     *  or null when the result of the original query was returned.
146     */
147    public function getQueryAfterRewrite() {
148        return $this->delegate->getQueryAfterRewrite();
149    }
150
151    /**
152     * @return string|null Same as self::getQueryAfterRewrite(), but in HTML
153     *  and with changes highlighted. Null when the query was not rewritten.
154     */
155    public function getQueryAfterRewriteSnippet() {
156        return $this->delegate->getQueryAfterRewriteSnippet();
157    }
158
159    /**
160     * Some search modes return a suggested alternate term if there are
161     * no exact hits. Returns true if there is one on this set.
162     *
163     * @return bool
164     */
165    public function hasSuggestion() {
166        return $this->delegate->hasSuggestion();
167    }
168
169    /**
170     * @return string|null Suggested query, null if none
171     */
172    public function getSuggestionQuery() {
173        return $this->delegate->getSuggestionQuery();
174    }
175
176    /**
177     * @return string HTML highlighted suggested query, '' if none
178     */
179    public function getSuggestionSnippet() {
180        return $this->delegate->getSuggestionSnippet();
181    }
182
183    /**
184     * Return a result set of hits on other (multiple) wikis associated with this one
185     *
186     * @param int $type
187     * @return ISearchResultSet[]
188     */
189    public function getInterwikiResults( $type = self::SECONDARY_RESULTS ) {
190        return $this->delegate->getInterwikiResults( $type );
191    }
192
193    /**
194     * Check if there are results on other wikis
195     *
196     * @param int $type
197     * @return bool
198     */
199    public function hasInterwikiResults( $type = self::SECONDARY_RESULTS ) {
200        return $this->delegate->hasInterwikiResults( $type );
201    }
202
203    /**
204     * Did the search contain search syntax?  If so, Special:Search won't offer
205     * the user a link to a create a page named by the search string because the
206     * name would contain the search syntax.
207     * @return bool
208     */
209    public function searchContainedSyntax() {
210        return $this->delegate->searchContainedSyntax();
211    }
212
213    /**
214     * @return bool True when there are more pages of search results available.
215     */
216    public function hasMoreResults() {
217        return $this->delegate->hasMoreResults();
218    }
219
220    /**
221     * @param int $limit Shrink result set to $limit and flag
222     *  if more results are available.
223     */
224    public function shrink( $limit ) {
225        if ( $this->count() > $limit ) {
226            $this->results = array_slice( $this->results, 0, $limit );
227        }
228        $this->delegate->shrink( $limit );
229    }
230
231    /**
232     * Extract all the titles in the result set.
233     * @return Title[]
234     */
235    public function extractTitles() {
236        return $this->delegate->extractTitles();
237    }
238
239    /**
240     * @param string $suggestionQuery
241     * @param HtmlArmor|string|null $suggestionSnippet
242     */
243    public function setSuggestionQuery( string $suggestionQuery, $suggestionSnippet = null ) {
244        $this->delegate->setSuggestionQuery( $suggestionQuery, $suggestionSnippet );
245    }
246}