Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
67.44% |
29 / 43 |
|
42.86% |
3 / 7 |
CRAP | |
0.00% |
0 / 1 |
FullTextResultsType | |
67.44% |
29 / 43 |
|
42.86% |
3 / 7 |
13.45 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getSourceFiltering | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
getFields | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHighlightingConfiguration | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
transformElasticsearchResult | |
64.29% |
18 / 28 |
|
0.00% |
0 / 1 |
4.73 | |||
withFetchPhaseBuilder | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
createEmptyResult | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | namespace CirrusSearch\Search; |
4 | |
5 | use CirrusSearch\Search\Fetch\FetchPhaseConfigBuilder; |
6 | use CirrusSearch\Util; |
7 | use Elastica\ResultSet as ElasticaResultSet; |
8 | use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface; |
9 | |
10 | /** |
11 | * Result type for a full text search. |
12 | */ |
13 | final class FullTextResultsType extends BaseResultsType { |
14 | /** |
15 | * @var bool |
16 | */ |
17 | private $searchContainedSyntax; |
18 | |
19 | /** |
20 | * @var FetchPhaseConfigBuilder |
21 | */ |
22 | private $fetchPhaseBuilder; |
23 | /** |
24 | * @var TitleHelper |
25 | */ |
26 | private $titleHelper; |
27 | |
28 | /** |
29 | * @var string[] list of extra fields to extract |
30 | */ |
31 | private $extraFieldsToExtract; |
32 | |
33 | /** |
34 | * @var bool if true, deduplicate results from file namespace |
35 | */ |
36 | private bool $deduplicate; |
37 | |
38 | /** |
39 | * @param FetchPhaseConfigBuilder $fetchPhaseBuilder |
40 | * @param bool $searchContainedSyntax |
41 | * @param TitleHelper $titleHelper |
42 | * @param string[] $extraFieldsToExtract |
43 | * @param bool $deduplicate |
44 | */ |
45 | public function __construct( |
46 | FetchPhaseConfigBuilder $fetchPhaseBuilder, |
47 | $searchContainedSyntax, |
48 | TitleHelper $titleHelper, |
49 | array $extraFieldsToExtract = [], |
50 | bool $deduplicate = false |
51 | ) { |
52 | $this->fetchPhaseBuilder = $fetchPhaseBuilder; |
53 | $this->searchContainedSyntax = $searchContainedSyntax; |
54 | $this->titleHelper = $titleHelper; |
55 | $this->extraFieldsToExtract = $extraFieldsToExtract; |
56 | $this->deduplicate = $deduplicate; |
57 | } |
58 | |
59 | /** |
60 | * @return false|string|array corresponding to Elasticsearch source filtering syntax |
61 | */ |
62 | public function getSourceFiltering() { |
63 | return array_merge( |
64 | parent::getSourceFiltering(), |
65 | [ 'redirect.*', 'timestamp', 'text_bytes' ], |
66 | $this->extraFieldsToExtract |
67 | ); |
68 | } |
69 | |
70 | /** |
71 | * @return array |
72 | */ |
73 | public function getFields() { |
74 | return [ "text.word_count" ]; // word_count is only a stored field and isn't part of the source. |
75 | } |
76 | |
77 | /** |
78 | * Setup highlighting. |
79 | * Don't fragment title because it is small. |
80 | * Get just one fragment from the text because that is all we will display. |
81 | * Get one fragment from redirect title and heading each or else they |
82 | * won't be sorted by score. |
83 | * |
84 | * @param array $extraHighlightFields (deprecated and ignored) |
85 | * @return array|null of highlighting configuration |
86 | */ |
87 | public function getHighlightingConfiguration( array $extraHighlightFields = [] ) { |
88 | $this->fetchPhaseBuilder->configureDefaultFullTextFields(); |
89 | return $this->fetchPhaseBuilder->buildHLConfig(); |
90 | } |
91 | |
92 | /** |
93 | * @param ElasticaResultSet $result |
94 | * @return CirrusSearchResultSet |
95 | */ |
96 | public function transformElasticsearchResult( ElasticaResultSet $result ) { |
97 | // Should we make this a concrete class? |
98 | return new class( |
99 | $this->titleHelper, |
100 | $this->fetchPhaseBuilder, |
101 | $result, |
102 | $this->searchContainedSyntax, |
103 | $this->extraFieldsToExtract, |
104 | $this->deduplicate |
105 | ) |
106 | extends BaseCirrusSearchResultSet { |
107 | /** @var TitleHelper */ |
108 | private $titleHelper; |
109 | /** @var FullTextCirrusSearchResultBuilder */ |
110 | private $resultBuilder; |
111 | /** @var ElasticaResultSet */ |
112 | private $results; |
113 | /** @var bool */ |
114 | private $searchContainedSyntax; |
115 | /** @var bool if true, deduplicate results from file namespace */ |
116 | private bool $deduplicate; |
117 | /** @var string[] array of titles for counting duplicates */ |
118 | private array $fileTitles = []; |
119 | /** @var StatsdDataFactoryInterface metrics facade */ |
120 | private StatsdDataFactoryInterface $statsd; |
121 | |
122 | public function __construct( |
123 | TitleHelper $titleHelper, |
124 | FetchPhaseConfigBuilder $builder, |
125 | ElasticaResultSet $results, |
126 | $searchContainedSyntax, |
127 | array $extraFieldsToExtract, |
128 | bool $deduplicate |
129 | ) { |
130 | $this->titleHelper = $titleHelper; |
131 | $this->resultBuilder = new FullTextCirrusSearchResultBuilder( $this->titleHelper, |
132 | $builder->getHLFieldsPerTargetAndPriority(), $extraFieldsToExtract ); |
133 | $this->results = $results; |
134 | $this->searchContainedSyntax = $searchContainedSyntax; |
135 | $this->statsd = Util::getStatsDataFactory(); |
136 | $this->deduplicate = $deduplicate; |
137 | } |
138 | |
139 | /** |
140 | * @inheritDoc |
141 | */ |
142 | protected function transformOneResult( \Elastica\Result $result ) { |
143 | $source = $result->getSource(); |
144 | if ( $source['namespace'] === NS_FILE ) { |
145 | if ( in_array( $source['title'], $this->fileTitles ) ) { |
146 | $this->statsd->increment( 'CirrusSearch.results.file_duplicates' ); |
147 | if ( $this->deduplicate ) { |
148 | return null; |
149 | } |
150 | } else { |
151 | $this->fileTitles[] = $source['title']; |
152 | } |
153 | } |
154 | return $this->resultBuilder->build( $result ); |
155 | } |
156 | |
157 | /** |
158 | * @return \Elastica\ResultSet|null |
159 | */ |
160 | public function getElasticaResultSet() { |
161 | return $this->results; |
162 | } |
163 | |
164 | /** |
165 | * @inheritDoc |
166 | */ |
167 | public function searchContainedSyntax() { |
168 | return $this->searchContainedSyntax; |
169 | } |
170 | |
171 | protected function getTitleHelper(): TitleHelper { |
172 | return $this->titleHelper; |
173 | } |
174 | }; |
175 | } |
176 | |
177 | /** |
178 | * @param FetchPhaseConfigBuilder $builder |
179 | * @return FullTextResultsType |
180 | */ |
181 | public function withFetchPhaseBuilder( FetchPhaseConfigBuilder $builder ): FullTextResultsType { |
182 | return new self( $builder, $this->searchContainedSyntax, $this->titleHelper, $this->extraFieldsToExtract, $this->deduplicate ); |
183 | } |
184 | |
185 | /** |
186 | * @return CirrusSearchResultSet |
187 | */ |
188 | public function createEmptyResult() { |
189 | return BaseCirrusSearchResultSet::emptyResultSet(); |
190 | } |
191 | } |