Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
ConfigDump
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 8
342
0.00% covered (danger)
0.00%
0 / 1
 execute
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
42
 addGlobals
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 addConcreteNamespaceMap
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 addReplicaGroup
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 addProfiles
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 addUserTesting
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace CirrusSearch\Api;
4
5use ApiBase;
6use ApiResult;
7use CirrusSearch\Profile\SearchProfileService;
8use CirrusSearch\SearchConfig;
9use CirrusSearch\UserTestingEngine;
10use MediaWiki\MediaWikiServices;
11use Wikimedia\ParamValidator\ParamValidator;
12
13/**
14 * Dumps CirrusSearch configuration for easy viewing.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 * http://www.gnu.org/copyleft/gpl.html
30 */
31class ConfigDump extends ApiBase {
32    use ApiTrait;
33
34    public static $PUBLICLY_SHAREABLE_CONFIG_VARS = [
35        'CirrusSearchDisableUpdate',
36        'CirrusSearchServers',
37        'CirrusSearchConnectionAttempts',
38        'CirrusSearchSlowSearch',
39        'CirrusSearchUseExperimentalHighlighter',
40        'CirrusSearchOptimizeIndexForExperimentalHighlighter',
41        'CirrusSearchNamespaceMappings',
42        'CirrusSearchExtraIndexes',
43        'CirrusSearchExtraIndexClusters',
44        'CirrusSearchFetchConfigFromApi',
45        'CirrusSearchUpdateShardTimeout',
46        'CirrusSearchClientSideUpdateTimeout',
47        'CirrusSearchSearchShardTimeout',
48        'CirrusSearchClientSizeSearchTimeout',
49        'CirrusSearchMaintenanceTimeout',
50        'CirrusSearchPrefixSearchStartsWithAnyWord',
51        'CirrusSearchPhraseSlop',
52        'CirrusSearchPhraseRescoreBoost',
53        'CirrusSearchPhraseRescoreWindowSize',
54        'CirrusSearchFunctionRescoreWindowSize',
55        'CirrusSearchMoreAccurateScoringMode',
56        'CirrusSearchPhraseSuggestUseText',
57        'CirrusSearchPhraseSuggestUseOpeningText',
58        'CirrusSearchIndexedRedirects',
59        'CirrusSearchLinkedArticlesToUpdate',
60        'CirrusSearchUnlikedArticlesToUpdate',
61        'CirrusSearchWeights',
62        'CirrusSearchBoostOpening',
63        'CirrusSearchNearMatchWeight',
64        'CirrusSearchStemmedWeight',
65        'CirrusSearchNamespaceWeights',
66        'CirrusSearchDefaultNamespaceWeight',
67        'CirrusSearchTalkNamespaceWeight',
68        'CirrusSearchLanguageWeight',
69        'CirrusSearchPreferRecentDefaultDecayPortion',
70        'CirrusSearchPreferRecentUnspecifiedDecayPortion',
71        'CirrusSearchPreferRecentDefaultHalfLife',
72        'CirrusSearchMoreLikeThisConfig',
73        'CirrusSearchInterwikiSources',
74        'CirrusSearchRefreshInterval',
75        'CirrusSearchFragmentSize',
76        'CirrusSearchIndexAllocation',
77        'CirrusSearchFullTextQueryBuilderProfile',
78        'CirrusSearchRescoreProfile',
79        'CirrusSearchPrefixSearchRescoreProfile',
80        'CirrusSearchSimilarityProfile',
81        'CirrusSearchCrossProjectProfiles',
82        'CirrusSearchCrossProjectOrder',
83        'CirrusSearchCrossProjectSearchBlockList',
84        'CirrusSearchExtraIndexBoostTemplates',
85        'CirrusSearchEnableCrossProjectSearch',
86        'CirrusSearchEnableAltLanguage',
87        'CirrusSearchEnableArchive',
88        'CirrusSearchUseIcuFolding',
89        'CirrusSearchUseIcuTokenizer',
90        'CirrusSearchPhraseSuggestProfiles',
91        'CirrusSearchCrossProjectBlockScorerProfiles',
92        'CirrusSearchSimilarityProfiles',
93        'CirrusSearchRescoreFunctionChains',
94        'CirrusSearchCompletionProfiles',
95        'CirrusSearchCompletionSettings',
96        'CirrusSearchCompletionSuggesterUseDefaultSort',
97        // All the config below was added when moving this data
98        // from CirrusSearch config to a static array in this class
99        'CirrusSearchDevelOptions',
100        'CirrusSearchPrefixIds',
101        'CirrusSearchMoreLikeThisFields',
102        'CirrusSearchMoreLikeThisTTL',
103        'CirrusSearchFiletypeAliases',
104        'CirrusSearchDefaultCluster',
105        'CirrusSearchClientSideConnectTimeout',
106        'CirrusSearchClusters',
107        'CirrusSearchReplicaGroup',
108        'CirrusSearchExtraBackendLatency',
109        'CirrusSearchAllowLeadingWildcard',
110        'CirrusSearchClientSideSearchTimeout',
111        'CirrusSearchStripQuestionMarks',
112        'CirrusSearchFullTextQueryBuilderProfiles',
113        'CirrusSearchEnableRegex',
114        'CirrusSearchWikimediaExtraPlugin',
115        'CirrusSearchRegexMaxDeterminizedStates',
116        'CirrusSearchMaxIncategoryOptions',
117        'CirrusSearchEnablePhraseSuggest',
118        'CirrusSearchClusterOverrides',
119        'CirrusSearchRescoreProfiles',
120        'CirrusSearchRescoreFunctionScoreChains',
121        'CirrusSearchNumCrossProjectSearchResults',
122        'CirrusSearchLanguageToWikiMap',
123        'CirrusSearchWikiToNameMap',
124        'CirrusSearchIncLinksAloneW',
125        'CirrusSearchIncLinksAloneK',
126        'CirrusSearchIncLinksAloneA',
127        'CirrusSearchNewCrossProjectPage',
128        'CirrusSearchQueryStringMaxDeterminizedStates',
129        'CirrusSearchElasticQuirks',
130        'CirrusSearchPhraseSuggestMaxErrors',
131        'CirrusSearchPhraseSuggestReverseField',
132        'CirrusSearchBoostTemplates',
133        'CirrusSearchIgnoreOnWikiBoostTemplates',
134        'CirrusSearchIndexBaseName',
135        'CirrusSearchInterleaveConfig',
136        'CirrusSearchMaxPhraseTokens',
137        'LanguageCode',
138        'ContentNamespaces',
139        'NamespacesToBeSearchedDefault',
140        'CirrusSearchCategoryDepth',
141        'CirrusSearchCategoryMax',
142        'CirrusSearchCategoryEndpoint',
143        'CirrusSearchFallbackProfile',
144        'CirrusSearchFallbackProfiles',
145    ];
146
147    public function execute() {
148        $result = $this->getResult();
149        $props = array_flip( $this->extractRequestParams()[ 'prop' ] );
150        if ( isset( $props['globals'] ) ) {
151            $this->addGlobals( $result );
152        }
153        if ( isset( $props['namespacemap'] ) ) {
154            $this->addConcreteNamespaceMap( $result );
155        }
156        if ( isset( $props['profiles'] ) ) {
157            $this->addProfiles( $result );
158        }
159        if ( isset( $props['replicagroup'] ) ) {
160            $this->addReplicaGroup( $result );
161        }
162        if ( isset( $props['usertesting'] ) ) {
163            $this->addUserTesting( $result );
164        }
165    }
166
167    protected function addGlobals( ApiResult $result ) {
168        $config = $this->getConfig();
169        foreach ( self::$PUBLICLY_SHAREABLE_CONFIG_VARS as $key ) {
170            if ( $config->has( $key ) ) {
171                $result->addValue( null, $key, $config->get( $key ) );
172            }
173        }
174    }
175
176    /**
177     * Include a complete mapping from namespace id to index containing pages.
178     *
179     * Intended for external services/users that need to interact
180     * with elasticsearch or cirrussearch dumps directly.
181     *
182     * @param ApiResult $result Impl to write results to
183     */
184    private function addConcreteNamespaceMap( ApiResult $result ) {
185        $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
186        $conn = $this->getCirrusConnection();
187        $indexBaseName = $conn->getConfig()->get( SearchConfig::INDEX_BASE_NAME );
188        foreach ( $nsInfo->getValidNamespaces() as $ns ) {
189            $indexSuffix = $conn->getIndexSuffixForNamespace( $ns );
190            $indexName = $conn->getIndexName( $indexBaseName, $indexSuffix );
191            $result->addValue( 'CirrusSearchConcreteNamespaceMap', $ns, $indexName );
192        }
193    }
194
195    private function addReplicaGroup( ApiResult $result ) {
196        $result->addValue( null, 'CirrusSearchConcreteReplicaGroup',
197            $this->getCirrusConnection()->getConfig()->getClusterAssignment()->getCrossClusterName() );
198    }
199
200    /**
201     * Profile names and types
202     * @var string[]
203     */
204    private static $PROFILES = [
205        'CirrusSearchPhraseSuggestProfiles' => SearchProfileService::PHRASE_SUGGESTER,
206        'CirrusSearchCrossProjectBlockScorerProfiles' => SearchProfileService::CROSS_PROJECT_BLOCK_SCORER,
207        'CirrusSearchSimilarityProfiles' => SearchProfileService::SIMILARITY,
208        'CirrusSearchRescoreFunctionChains' => SearchProfileService::RESCORE_FUNCTION_CHAINS,
209        'CirrusSearchCompletionProfiles' => SearchProfileService::COMPLETION,
210        'CirrusSearchFullTextQueryBuilderProfiles' => SearchProfileService::FT_QUERY_BUILDER,
211        'CirrusSearchRescoreProfiles' => SearchProfileService::RESCORE,
212    ];
213
214    /**
215     * Add data from profiles
216     * @param ApiResult $result
217     */
218    private function addProfiles( ApiResult $result ) {
219        $config = new SearchConfig();
220        $profileService = $config->getProfileService();
221        foreach ( self::$PROFILES as $var => $profileType ) {
222            $data = $profileService->listExposedProfiles( $profileType );
223            $this->getResult()->addValue( null, $var, $data, ApiResult::OVERRIDE );
224        }
225    }
226
227    protected function addUserTesting( ApiResult $result ) {
228        // UserTesting only automatically assigns test buckets during web requests.
229        // This api call is different from a typical search request though, this is
230        // used from non-search pages to find out what bucket to provide to a new
231        // autocomplete session.
232        $engine = UserTestingEngine::fromConfig( $this->getConfig() );
233        $status = $engine->decideTestByAutoenroll();
234        $result->addValue( null, 'CirrusSearchActiveUserTest',
235            $status->isActive() ? $status->getTrigger() : '' );
236    }
237
238    public function getAllowedParams() {
239        return [
240            'prop' => [
241                ParamValidator::PARAM_DEFAULT => 'globals|namespacemap|profiles|replicagroup',
242                ParamValidator::PARAM_TYPE => [
243                    'globals',
244                    'namespacemap',
245                    'profiles',
246                    'replicagroup',
247                    'usertesting',
248                ],
249                ParamValidator::PARAM_ISMULTI => true,
250            ],
251        ];
252    }
253
254    /**
255     * @see ApiBase::getExamplesMessages
256     * @return array
257     */
258    protected function getExamplesMessages() {
259        return [
260            'action=cirrus-config-dump' =>
261                'apihelp-cirrus-config-dump-example'
262        ];
263    }
264
265}