Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
ManageMessageGroupSubscriptionsSpecialPage.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\PageTranslation;
5
6use EditWatchlistCheckboxSeriesField;
7use EditWatchlistNormalHTMLForm;
10use MediaWiki\Html\Html;
11use MediaWiki\HTMLForm\HTMLForm;
12use MediaWiki\HTMLForm\OOUIHTMLForm;
13use MediaWiki\SpecialPage\SpecialPage;
14use MediaWiki\SpecialPage\UnlistedSpecialPage;
15use MediaWiki\Status\Status;
16use MessageGroup;
17use UserNotLoggedIn;
18
26class ManageMessageGroupSubscriptionsSpecialPage extends UnlistedSpecialPage {
27 private const EDIT_RAW = 'raw';
28 private const NS_INVALID = 99999;
29
30 private const WATCHLIST_TAB_PATHS = [
31 'Special:ManageMessageGroupSubscriptions',
32 'Special:ManageMessageGroupSubscriptions/raw',
33 ];
34
35 private MessageGroupSubscription $messageGroupSubscription;
36
37 public function __construct( MessageGroupSubscription $messageGroupSubscription ) {
38 parent::__construct( 'ManageMessageGroupSubscriptions' );
39 $this->messageGroupSubscription = $messageGroupSubscription;
40 }
41
43 public function doesWrites() {
44 return true;
45 }
46
48 public function execute( $mode ) {
49 $this->setHeaders();
50
51 $user = $this->getUser();
52 if ( !$user->isNamed() ) {
53 throw new UserNotLoggedIn( 'tpt-manage-message-group-subscriptions-list-anon-text' );
54 }
55
56 $out = $this->getOutput();
57
58 $this->checkReadOnly();
59
60 $this->outputHeader();
61 $out->addModuleStyles( [
62 'mediawiki.interface.helpers.styles',
63 'mediawiki.special',
64 'ext.translate.special.managemessagegroupsubscriptions.styles'
65 ] );
66 $out->addModules( [ 'ext.translate.special.managemessagegroupsubscriptions' ] );
67
68 switch ( $mode ) {
69 case self::EDIT_RAW:
70 $this->executeRawEditForm();
71 break;
72 default:
73 $this->executeNormalEditForm();
74 break;
75 }
76 }
77
79 private function executeRawEditForm(): void {
80 $out = $this->getOutput();
81 $out->setPageTitleMsg( $this->msg( 'tpt-manage-message-group-subscriptions-edit-raw-title' ) );
82 $form = $this->getRawForm();
83 if ( $form->show() ) {
84 $out->addReturnTo( SpecialPage::getTitleFor( 'ManageMessageGroupSubscriptions' ) );
85 }
86 }
87
89 private function executeNormalEditForm(): void {
90 $out = $this->getOutput();
91 $out->setPageTitleMsg( $this->msg( 'tpt-manage-message-group-subscriptions-edit-normal-title' ) );
92
93 $form = $this->getNormalForm();
94 $form->prepareForm();
95
96 $result = $form->tryAuthorizedSubmit();
97 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
98 $out->addReturnTo( SpecialPage::getTitleFor( 'ManageMessageGroupSubscriptions' ) );
99 return;
100 }
101
102 $form->displayForm( $result );
103 }
104
106 public function getAssociatedNavigationLinks(): array {
107 return self::WATCHLIST_TAB_PATHS;
108 }
109
114 public function getSubpagesForPrefixSearch(): array {
115 // ManageMessageGroupSubscriptions uses ManageMessageGroupSubscriptions::getMode, so new types should be added
116 // here.
117 return [
118 self::EDIT_RAW,
119 ];
120 }
121
122 public function submitRaw( array $data ): bool {
123 $retainedLines = trim( $data['Titles'] );
124 $retainedGroups = $retainedLines ? array_map( 'trim', explode( "\n", $retainedLines ) ) : [];
125 $current = $this->messageGroupSubscription->getUserSubscriptions( $this->getUser() );
126
127 $toSubscribe = array_diff( $retainedGroups, $current );
128 $toUnsubscribe = array_diff( $current, $retainedGroups );
129 if ( !$toSubscribe && !$toUnsubscribe ) {
130 return false;
131 }
132
133 $this->messageGroupSubscription->subscribeToGroupsById( $toSubscribe, $this->getUser() );
134 $this->messageGroupSubscription->unsubscribeFromGroupsById( $toUnsubscribe, $this->getUser() );
135
136 $this->getUser()->invalidateCache();
137 $successMessage = Html::element(
138 'p',
139 [],
140 $this->msg( 'tpt-manage-message-group-subscriptions-raw-done' )->text()
141 );
142
143 if ( $toSubscribe ) {
144 $successMessage .= Html::element(
145 'p',
146 [],
147 $this->msg( 'tpt-manage-message-group-subscriptions-raw-added' )
148 ->numParams( count( $toSubscribe ) )
149 ->text()
150 );
151 $successMessage .= $this->showTitles( $toSubscribe );
152 }
153
154 if ( $toUnsubscribe ) {
155 $successMessage .= Html::element(
156 'p',
157 [],
158 $this->msg( 'tpt-manage-message-group-subscriptions-raw-removed' )
159 ->numParams( count( $toUnsubscribe ) )
160 ->text()
161 );
162 $successMessage .= $this->showTitles( $toUnsubscribe );
163 }
164
165 $this->getOutput()->addHTML( $successMessage );
166 return true;
167 }
168
170 private function showTitles( array $messageGroupsIds ): string {
171 if ( count( $messageGroupsIds ) >= 100 ) {
172 return $this->msg( 'tpt-manage-message-group-subscriptions-too-many' )->parse();
173 }
174
175 // Print out the list
176 $output = "<ul>\n";
177 $linkRenderer = $this->getLinkRenderer();
178 foreach ( $messageGroupsIds as $messageGroupId ) {
179 if ( $messageGroupId === "" ) {
180 continue;
181 }
182
183 $messageGroup = MessageGroups::getGroup( $messageGroupId );
184 if ( !$messageGroup ) {
185 $output .= Html::element( 'li', [], $messageGroupId ) . "\n";
186 continue;
187 }
188
189 $output .= '<li>' .
190 $linkRenderer->makeKnownLink(
191 SpecialPage::getTitleFor( 'Translate' ),
192 $messageGroup->getLabel(),
193 [],
194 [
195 'group' => $messageGroupId,
196 ]
197 ) .
198 "</li>\n";
199 }
200
201 $output .= "</ul>\n";
202 return $output;
203 }
204
211 private function getMessageGroupSubscriptionInfo(): array {
212 $labels = [];
213
214 $subscribedItems = $this->messageGroupSubscription->getUserSubscriptions( $this->getUser() );
215 foreach ( $subscribedItems as $subscriptionItem ) {
216 $messageGroup = MessageGroups::getGroup( $subscriptionItem );
217 if ( !$messageGroup ) {
218 $labels[self::NS_INVALID][$subscriptionItem] = $subscriptionItem;
219 continue;
220 }
221
222 // For items with other namespaces that don't exist in Translate but broader MediaWiki
223 $relatedPage = $messageGroup->getRelatedPage();
224 $namespace = $relatedPage ? $relatedPage->getNamespace() : $messageGroup->getNamespace();
225
226 $groupLabel = $messageGroup->getLabel();
227 $labels[$namespace][$groupLabel] = $messageGroup;
228 }
229 return $labels;
230 }
231
232 public function submitNormal( array $data ): bool {
233 $toRemove = [];
234
235 foreach ( $data as $messageGroups ) {
236 // ignore the 'check all' checkbox, which is a boolean value
237 if ( is_array( $messageGroups ) ) {
238 $toRemove = array_merge( $toRemove, $messageGroups );
239 }
240 }
241
242 if ( count( $toRemove ) > 0 ) {
243 $this->messageGroupSubscription->unsubscribeFromGroupsById( $toRemove, $this->getUser() );
244 $successMessage = $this->msg( 'tpt-manage-message-group-subscriptions-normal-done' )
245 ->numParams( count( $toRemove ) )
246 ->parse();
247 $successMessage .= $this->showTitles( $toRemove );
248 $this->getOutput()->addHTML( $successMessage );
249 return true;
250 }
251
252 return false;
253 }
254
256 private function getNormalForm(): HTMLForm {
257 $fields = [];
258
259 // Allow subscribers to manipulate the list of watched pages (or use it
260 // to preload lots of details at once)
261 $subscriptionInfo = $this->getMessageGroupSubscriptionInfo();
262
263 foreach ( $subscriptionInfo as $namespace => $messageGroups ) {
264 $options = [];
265 foreach ( $messageGroups as $messageGroup ) {
266 if ( is_string( $messageGroup ) ) {
267 $options[htmlspecialchars( $messageGroup )] = $messageGroup;
268 } else {
269 $text = $this->buildRemoveLine( $messageGroup );
270 $options[$text] = $messageGroup->getId();
271 }
272 }
273 ksort( $options );
274
275 // checkTitle can filter some options out, avoid empty sections
276 if ( count( $options ) > 0 ) {
277 // add a checkbox to select all entries in namespace
278 $fields['CheckAllNs' . $namespace] = [
279 'cssclass' => 'tpt-manage-subscriptions-messagegroups-checkall',
280 'type' => 'check',
281 'section' => "ns$namespace",
282 'label' => $this->msg( 'tpt-manage-message-group-subscriptions-normal-check-all' )->text()
283 ];
284
285 $fields['TitlesNs' . $namespace] = [
286 'cssclass' => 'tpt-manage-message-group-subscriptions-messagegroups-check',
287 'class' => EditWatchlistCheckboxSeriesField::class,
288 'options' => $options,
289 'section' => "ns$namespace",
290 ];
291 }
292 }
293
294 $form = new EditWatchlistNormalHTMLForm( $fields, $this->getContext() );
295 $form->setTitle( $this->getPageTitle() ); // Remove subpage
296 $form->setSubmitTextMsg( 'tpt-manage-message-group-subscriptions-normal-submit' );
297 $form->setSubmitDestructive();
298 $form->setSubmitTooltip( 'tpt-manage-message-group-subscriptions-normal-submit' );
299 $form->setWrapperLegendMsg( 'tpt-manage-message-group-subscriptions-normal-legend' );
300 $form->addHeaderHtml( $this->msg( 'tpt-manage-message-group-subscriptions-normal-explain' )->parse() );
301 $form->setSubmitCallback( [ $this, 'submitNormal' ] );
302
303 return $form;
304 }
305
307 private function buildRemoveLine( MessageGroup $messageGroup ): string {
308 return $this->getLinkRenderer()->makeKnownLink(
309 SpecialPage::getTitleFor( 'Translate' ),
310 $messageGroup->getLabel(),
311 [],
312 [
313 'group' => $messageGroup->getId(),
314 ]
315 );
316 }
317
319 private function getRawForm(): HTMLForm {
320 $messageGroupIds = $this->messageGroupSubscription->getUserSubscriptions( $this->getUser() );
321 $labels = implode( "\n", $messageGroupIds );
322
323 $fields = [
324 'Titles' => [
325 'type' => 'textarea',
326 'label-message' => 'tpt-manage-message-group-subscriptions-raw-titles',
327 'default' => $labels,
328 ],
329 ];
330 $form = new OOUIHTMLForm( $fields, $this->getContext() );
331 $form->setTitle( $this->getPageTitle( 'raw' ) ); // Reset subpage
332 $form->setSubmitTextMsg( 'tpt-manage-message-group-subscriptions-raw-submit' );
333 $form->setSubmitTooltip( 'tpt-manage-message-group-subscriptions-raw-submit' );
334 $form->setWrapperLegendMsg( 'tpt-manage-message-group-subscriptions-raw-legend' );
335 $form->addHeaderHtml( $this->msg( 'tpt-manage-message-group-subscriptions-raw-explain' )->parse() );
336 $form->setSubmitCallback( [ $this, 'submitRaw' ] );
337
338 return $form;
339 }
340}
return[ 'Translate:AggregateGroupManager'=> static function(MediaWikiServices $services):AggregateGroupManager { return new AggregateGroupManager($services->getTitleFactory(), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:AggregateGroupMessageGroupFactory'=> static function(MediaWikiServices $services):AggregateGroupMessageGroupFactory { return new AggregateGroupMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:ConfigHelper'=> static function():ConfigHelper { return new ConfigHelper();}, 'Translate:CsvTranslationImporter'=> static function(MediaWikiServices $services):CsvTranslationImporter { return new CsvTranslationImporter( $services->getWikiPageFactory());}, 'Translate:EntitySearch'=> static function(MediaWikiServices $services):EntitySearch { return new EntitySearch($services->getMainWANObjectCache(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), MessageGroups::singleton(), $services->getNamespaceInfo(), $services->get( 'Translate:MessageIndex'), $services->getTitleParser(), $services->getTitleFormatter());}, 'Translate:ExternalMessageSourceStateComparator'=> static function(MediaWikiServices $services):ExternalMessageSourceStateComparator { return new ExternalMessageSourceStateComparator(new SimpleStringComparator(), $services->getRevisionLookup(), $services->getPageStore());}, 'Translate:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance(LogNames::GROUP_SYNCHRONIZATION), $services->get( 'Translate:MessageIndex'), $services->getTitleFactory(), $services->get( 'Translate:MessageGroupSubscription'), new ServiceOptions(ExternalMessageSourceStateImporter::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:FileBasedMessageGroupFactory'=> static function(MediaWikiServices $services):FileBasedMessageGroupFactory { return new FileBasedMessageGroupFactory(new MessageGroupConfigurationParser(), $services->getContentLanguageCode() ->toString(), new ServiceOptions(FileBasedMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:FileFormatFactory'=> static function(MediaWikiServices $services):FileFormatFactory { return new FileFormatFactory( $services->getObjectFactory());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:HookDefinedMessageGroupFactory'=> static function(MediaWikiServices $services):HookDefinedMessageGroupFactory { return new HookDefinedMessageGroupFactory( $services->get( 'Translate:HookRunner'));}, 'Translate:HookRunner'=> static function(MediaWikiServices $services):HookRunner { return new HookRunner( $services->getHookContainer());}, 'Translate:MessageBundleDependencyPurger'=> static function(MediaWikiServices $services):MessageBundleDependencyPurger { return new MessageBundleDependencyPurger( $services->get( 'Translate:TranslatableBundleFactory'));}, 'Translate:MessageBundleMessageGroupFactory'=> static function(MediaWikiServices $services):MessageBundleMessageGroupFactory { return new MessageBundleMessageGroupFactory($services->get( 'Translate:MessageGroupMetadata'), new ServiceOptions(MessageBundleMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore($services->get( 'Translate:RevTagStore'), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:MessageBundleTranslationLoader'=> static function(MediaWikiServices $services):MessageBundleTranslationLoader { return new MessageBundleTranslationLoader( $services->getLanguageFallback());}, 'Translate:MessageGroupMetadata'=> static function(MediaWikiServices $services):MessageGroupMetadata { return new MessageGroupMetadata( $services->getConnectionProvider());}, 'Translate:MessageGroupReviewStore'=> static function(MediaWikiServices $services):MessageGroupReviewStore { return new MessageGroupReviewStore($services->getConnectionProvider(), $services->get( 'Translate:HookRunner'));}, 'Translate:MessageGroupStatsTableFactory'=> static function(MediaWikiServices $services):MessageGroupStatsTableFactory { return new MessageGroupStatsTableFactory($services->get( 'Translate:ProgressStatsTableFactory'), $services->getLinkRenderer(), $services->get( 'Translate:MessageGroupReviewStore'), $services->get( 'Translate:MessageGroupMetadata'), $services->getMainConfig() ->get( 'TranslateWorkflowStates') !==false);}, 'Translate:MessageGroupSubscription'=> static function(MediaWikiServices $services):MessageGroupSubscription { return new MessageGroupSubscription($services->get( 'Translate:MessageGroupSubscriptionStore'), $services->getJobQueueGroup(), $services->getUserIdentityLookup(), LoggerFactory::getInstance(LogNames::GROUP_SUBSCRIPTION), new ServiceOptions(MessageGroupSubscription::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:MessageGroupSubscriptionHookHandler'=> static function(MediaWikiServices $services):?MessageGroupSubscriptionHookHandler { if(! $services->getExtensionRegistry() ->isLoaded( 'Echo')) { return null;} return new MessageGroupSubscriptionHookHandler($services->get( 'Translate:MessageGroupSubscription'), $services->getUserFactory());}, 'Translate:MessageGroupSubscriptionStore'=> static function(MediaWikiServices $services):MessageGroupSubscriptionStore { return new MessageGroupSubscriptionStore( $services->getConnectionProvider());}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=(array) $services->getMainConfig() ->get( 'TranslateMessageIndex');$class=array_shift( $params);$implementationMap=['HashMessageIndex'=> HashMessageIndex::class, 'CDBMessageIndex'=> CDBMessageIndex::class, 'DatabaseMessageIndex'=> DatabaseMessageIndex::class, 'hash'=> HashMessageIndex::class, 'cdb'=> CDBMessageIndex::class, 'database'=> DatabaseMessageIndex::class,];$messageIndexStoreClass=$implementationMap[$class] ?? $implementationMap['database'];return new MessageIndex(new $messageIndexStoreClass, $services->getMainWANObjectCache(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), LoggerFactory::getInstance(LogNames::MAIN), $services->getMainObjectStash(), $services->getConnectionProvider(), new ServiceOptions(MessageIndex::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:MessagePrefixStats'=> static function(MediaWikiServices $services):MessagePrefixStats { return new MessagePrefixStats( $services->getTitleParser());}, 'Translate:ParsingPlaceholderFactory'=> static function():ParsingPlaceholderFactory { return new ParsingPlaceholderFactory();}, 'Translate:PersistentCache'=> static function(MediaWikiServices $services):PersistentCache { return new PersistentDatabaseCache($services->getConnectionProvider(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:RevTagStore'=> static function(MediaWikiServices $services):RevTagStore { return new RevTagStore( $services->getConnectionProvider());}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleDeleter'=> static function(MediaWikiServices $services):TranslatableBundleDeleter { return new TranslatableBundleDeleter($services->getMainObjectStash(), $services->getJobQueueGroup(), $services->get( 'Translate:SubpageListBuilder'), $services->get( 'Translate:TranslatableBundleFactory'));}, 'Translate:TranslatableBundleExporter'=> static function(MediaWikiServices $services):TranslatableBundleExporter { return new TranslatableBundleExporter($services->get( 'Translate:SubpageListBuilder'), $services->getWikiExporterFactory(), $services->getConnectionProvider());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, 'Translate:TranslatableBundleImporter'=> static function(MediaWikiServices $services):TranslatableBundleImporter { return new TranslatableBundleImporter($services->getWikiImporterFactory(), $services->get( 'Translate:TranslatablePageParser'), $services->getRevisionLookup(), $services->getNamespaceInfo(), $services->getTitleFactory(), $services->getFormatterFactory());}, 'Translate:TranslatableBundleMover'=> static function(MediaWikiServices $services):TranslatableBundleMover { return new TranslatableBundleMover($services->getMovePageFactory(), $services->getJobQueueGroup(), $services->getLinkBatchFactory(), $services->get( 'Translate:TranslatableBundleFactory'), $services->get( 'Translate:SubpageListBuilder'), $services->getConnectionProvider(), $services->getObjectCacheFactory(), $services->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatableBundleStatusStore'=> static function(MediaWikiServices $services):TranslatableBundleStatusStore { return new TranslatableBundleStatusStore($services->getConnectionProvider() ->getPrimaryDatabase(), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), $services->getDBLoadBalancer() ->getMaintenanceConnectionRef(DB_PRIMARY));}, 'Translate:TranslatablePageMarker'=> static function(MediaWikiServices $services):TranslatablePageMarker { return new TranslatablePageMarker($services->getConnectionProvider(), $services->getJobQueueGroup(), $services->getLinkRenderer(), MessageGroups::singleton(), $services->get( 'Translate:MessageIndex'), $services->getTitleFormatter(), $services->getTitleParser(), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:TranslatablePageStateStore'), $services->get( 'Translate:TranslationUnitStoreFactory'), $services->get( 'Translate:MessageGroupMetadata'), $services->getWikiPageFactory(), $services->get( 'Translate:TranslatablePageView'), $services->get( 'Translate:MessageGroupSubscription'), $services->getFormatterFactory(), $services->get( 'Translate:HookRunner'),);}, 'Translate:TranslatablePageMessageGroupFactory'=> static function(MediaWikiServices $services):TranslatablePageMessageGroupFactory { return new TranslatablePageMessageGroupFactory(new ServiceOptions(TranslatablePageMessageGroupFactory::SERVICE_OPTIONS, $services->getMainConfig()),);}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStateStore'=> static function(MediaWikiServices $services):TranslatablePageStateStore { return new TranslatablePageStateStore($services->get( 'Translate:PersistentCache'), $services->getPageStore());}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), $services->get( 'Translate:RevTagStore'), $services->getConnectionProvider(), $services->get( 'Translate:TranslatableBundleStatusStore'), $services->get( 'Translate:TranslatablePageParser'), $services->get( 'Translate:MessageGroupMetadata'));}, 'Translate:TranslatablePageView'=> static function(MediaWikiServices $services):TranslatablePageView { return new TranslatablePageView($services->getConnectionProvider(), $services->get( 'Translate:TranslatablePageStateStore'), new ServiceOptions(TranslatablePageView::SERVICE_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslateSandbox'=> static function(MediaWikiServices $services):TranslateSandbox { return new TranslateSandbox($services->getUserFactory(), $services->getConnectionProvider(), $services->getPermissionManager(), $services->getAuthManager(), $services->getUserGroupManager(), $services->getActorStore(), $services->getUserOptionsManager(), $services->getJobQueueGroup(), $services->get( 'Translate:HookRunner'), new ServiceOptions(TranslateSandbox::CONSTRUCTOR_OPTIONS, $services->getMainConfig()));}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { return new TranslationStashStorage( $services->getConnectionProvider() ->getPrimaryDatabase());}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory(), $services->getConnectionProvider());}, 'Translate:TranslationUnitStoreFactory'=> static function(MediaWikiServices $services):TranslationUnitStoreFactory { return new TranslationUnitStoreFactory( $services->getDBLoadBalancer());}, 'Translate:TranslatorActivity'=> static function(MediaWikiServices $services):TranslatorActivity { $query=new TranslatorActivityQuery($services->getMainConfig(), $services->getDBLoadBalancer());return new TranslatorActivity($services->getMainObjectStash(), $query, $services->getJobQueueGroup());}, 'Translate:TtmServerFactory'=> static function(MediaWikiServices $services):TtmServerFactory { $config=$services->getMainConfig();$default=$config->get( 'TranslateTranslationDefaultService');if( $default===false) { $default=null;} return new TtmServerFactory( $config->get( 'TranslateTranslationServices'), $default);}, 'Translate:WorkflowStatesMessageGroupLoader'=> static function(MediaWikiServices $services):WorkflowStatesMessageGroupLoader { return new WorkflowStatesMessageGroupLoader(new ServiceOptions(WorkflowStatesMessageGroupLoader::CONSTRUCTOR_OPTIONS, $services->getMainConfig()),);},]
@phpcs-require-sorted-array
Manage user subscriptions to message groups and trigger notifications.
Factory class for accessing message groups individually by id or all of them as a list.
Interface for message groups.