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        'CirrusSearchAllFields',
63        'CirrusSearchBoostOpening',
64        'CirrusSearchNearMatchWeight',
65        'CirrusSearchStemmedWeight',
66        'CirrusSearchNamespaceWeights',
67        'CirrusSearchDefaultNamespaceWeight',
68        'CirrusSearchTalkNamespaceWeight',
69        'CirrusSearchLanguageWeight',
70        'CirrusSearchPreferRecentDefaultDecayPortion',
71        'CirrusSearchPreferRecentUnspecifiedDecayPortion',
72        'CirrusSearchPreferRecentDefaultHalfLife',
73        'CirrusSearchMoreLikeThisConfig',
74        'CirrusSearchInterwikiSources',
75        'CirrusSearchRefreshInterval',
76        'CirrusSearchFragmentSize',
77        'CirrusSearchIndexAllocation',
78        'CirrusSearchFullTextQueryBuilderProfile',
79        'CirrusSearchRescoreProfile',
80        'CirrusSearchPrefixSearchRescoreProfile',
81        'CirrusSearchSimilarityProfile',
82        'CirrusSearchCrossProjectProfiles',
83        'CirrusSearchCrossProjectOrder',
84        'CirrusSearchCrossProjectSearchBlockList',
85        'CirrusSearchExtraIndexBoostTemplates',
86        'CirrusSearchEnableCrossProjectSearch',
87        'CirrusSearchEnableAltLanguage',
88        'CirrusSearchEnableArchive',
89        'CirrusSearchUseIcuFolding',
90        'CirrusSearchUseIcuTokenizer',
91        'CirrusSearchPhraseSuggestProfiles',
92        'CirrusSearchCrossProjectBlockScorerProfiles',
93        'CirrusSearchSimilarityProfiles',
94        'CirrusSearchRescoreFunctionChains',
95        'CirrusSearchCompletionProfiles',
96        'CirrusSearchCompletionSettings',
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        'CirrusSearchAllFieldsForRescore',
135        'CirrusSearchIndexBaseName',
136        'CirrusSearchInterleaveConfig',
137        'CirrusSearchMaxPhraseTokens',
138        'LanguageCode',
139        'ContentNamespaces',
140        'NamespacesToBeSearchedDefault',
141        'CirrusSearchCategoryDepth',
142        'CirrusSearchCategoryMax',
143        'CirrusSearchCategoryEndpoint',
144        'CirrusSearchFallbackProfile',
145        'CirrusSearchFallbackProfiles',
146    ];
147
148    public function execute() {
149        $result = $this->getResult();
150        $props = array_flip( $this->extractRequestParams()[ 'prop' ] );
151        if ( isset( $props['globals'] ) ) {
152            $this->addGlobals( $result );
153        }
154        if ( isset( $props['namespacemap'] ) ) {
155            $this->addConcreteNamespaceMap( $result );
156        }
157        if ( isset( $props['profiles'] ) ) {
158            $this->addProfiles( $result );
159        }
160        if ( isset( $props['replicagroup'] ) ) {
161            $this->addReplicaGroup( $result );
162        }
163        if ( isset( $props['usertesting'] ) ) {
164            $this->addUserTesting( $result );
165        }
166    }
167
168    protected function addGlobals( ApiResult $result ) {
169        $config = $this->getConfig();
170        foreach ( self::$PUBLICLY_SHAREABLE_CONFIG_VARS as $key ) {
171            if ( $config->has( $key ) ) {
172                $result->addValue( null, $key, $config->get( $key ) );
173            }
174        }
175    }
176
177    /**
178     * Include a complete mapping from namespace id to index containing pages.
179     *
180     * Intended for external services/users that need to interact
181     * with elasticsearch or cirrussearch dumps directly.
182     *
183     * @param ApiResult $result Impl to write results to
184     */
185    private function addConcreteNamespaceMap( ApiResult $result ) {
186        $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
187        $conn = $this->getCirrusConnection();
188        $indexBaseName = $conn->getConfig()->get( SearchConfig::INDEX_BASE_NAME );
189        foreach ( $nsInfo->getValidNamespaces() as $ns ) {
190            $indexSuffix = $conn->getIndexSuffixForNamespace( $ns );
191            $indexName = $conn->getIndexName( $indexBaseName, $indexSuffix );
192            $result->addValue( 'CirrusSearchConcreteNamespaceMap', $ns, $indexName );
193        }
194    }
195
196    private function addReplicaGroup( ApiResult $result ) {
197        $result->addValue( null, 'CirrusSearchConcreteReplicaGroup',
198            $this->getCirrusConnection()->getConfig()->getClusterAssignment()->getCrossClusterName() );
199    }
200
201    /**
202     * Profile names and types
203     * @var string[]
204     */
205    private static $PROFILES = [
206        'CirrusSearchPhraseSuggestProfiles' => SearchProfileService::PHRASE_SUGGESTER,
207        'CirrusSearchCrossProjectBlockScorerProfiles' => SearchProfileService::CROSS_PROJECT_BLOCK_SCORER,
208        'CirrusSearchSimilarityProfiles' => SearchProfileService::SIMILARITY,
209        'CirrusSearchRescoreFunctionChains' => SearchProfileService::RESCORE_FUNCTION_CHAINS,
210        'CirrusSearchCompletionProfiles' => SearchProfileService::COMPLETION,
211        'CirrusSearchFullTextQueryBuilderProfiles' => SearchProfileService::FT_QUERY_BUILDER,
212        'CirrusSearchRescoreProfiles' => SearchProfileService::RESCORE,
213    ];
214
215    /**
216     * Add data from profiles
217     * @param ApiResult $result
218     */
219    private function addProfiles( ApiResult $result ) {
220        $config = new SearchConfig();
221        $profileService = $config->getProfileService();
222        foreach ( self::$PROFILES as $var => $profileType ) {
223            $data = $profileService->listExposedProfiles( $profileType );
224            $this->getResult()->addValue( null, $var, $data, ApiResult::OVERRIDE );
225        }
226    }
227
228    protected function addUserTesting( ApiResult $result ) {
229        // UserTesting only automatically assigns test buckets during web requests.
230        // This api call is different from a typical search request though, this is
231        // used from non-search pages to find out what bucket to provide to a new
232        // autocomplete session.
233        $engine = UserTestingEngine::fromConfig( $this->getConfig() );
234        $status = $engine->decideTestByAutoenroll();
235        $result->addValue( null, 'CirrusSearchActiveUserTest',
236            $status->isActive() ? $status->getTrigger() : '' );
237    }
238
239    public function getAllowedParams() {
240        return [
241            'prop' => [
242                ParamValidator::PARAM_DEFAULT => 'globals|namespacemap|profiles|replicagroup',
243                ParamValidator::PARAM_TYPE => [
244                    'globals',
245                    'namespacemap',
246                    'profiles',
247                    'replicagroup',
248                    'usertesting',
249                ],
250                ParamValidator::PARAM_ISMULTI => true,
251            ],
252        ];
253    }
254
255    /**
256     * @see ApiBase::getExamplesMessages
257     * @return array
258     */
259    protected function getExamplesMessages() {
260        return [
261            'action=cirrus-config-dump' =>
262                'apihelp-cirrus-config-dump-example'
263        ];
264    }
265
266}