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