27 private const EDIT_RAW =
'raw';
28 private const NS_INVALID = 99999;
30 private const WATCHLIST_TAB_PATHS = [
31 'Special:ManageMessageGroupSubscriptions',
32 'Special:ManageMessageGroupSubscriptions/raw',
38 parent::__construct(
'ManageMessageGroupSubscriptions' );
39 $this->messageGroupSubscription = $messageGroupSubscription;
51 $user = $this->getUser();
52 if ( !$user->isNamed() ) {
53 throw new UserNotLoggedIn(
'tpt-manage-message-group-subscriptions-list-anon-text' );
56 $out = $this->getOutput();
58 $this->checkReadOnly();
60 $this->outputHeader();
61 $out->addModuleStyles( [
62 'mediawiki.interface.helpers.styles',
64 'ext.translate.special.managemessagegroupsubscriptions.styles'
66 $out->addModules( [
'ext.translate.special.managemessagegroupsubscriptions' ] );
70 $this->executeRawEditForm();
73 $this->executeNormalEditForm();
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' ) );
89 private function executeNormalEditForm(): void {
90 $out = $this->getOutput();
91 $out->setPageTitleMsg( $this->msg(
'tpt-manage-message-group-subscriptions-edit-normal-title' ) );
93 $form = $this->getNormalForm();
96 $result = $form->tryAuthorizedSubmit();
97 if ( $result ===
true || ( $result instanceof Status && $result->isGood() ) ) {
98 $out->addReturnTo( SpecialPage::getTitleFor(
'ManageMessageGroupSubscriptions' ) );
102 $form->displayForm( $result );
107 return self::WATCHLIST_TAB_PATHS;
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() );
127 $toSubscribe = array_diff( $retainedGroups, $current );
128 $toUnsubscribe = array_diff( $current, $retainedGroups );
129 if ( !$toSubscribe && !$toUnsubscribe ) {
133 $this->messageGroupSubscription->subscribeToGroupsById( $toSubscribe, $this->getUser() );
134 $this->messageGroupSubscription->unsubscribeFromGroupsById( $toUnsubscribe, $this->getUser() );
136 $this->getUser()->invalidateCache();
137 $successMessage = Html::element(
140 $this->msg(
'tpt-manage-message-group-subscriptions-raw-done' )->text()
143 if ( $toSubscribe ) {
144 $successMessage .= Html::element(
147 $this->msg(
'tpt-manage-message-group-subscriptions-raw-added' )
148 ->numParams( count( $toSubscribe ) )
151 $successMessage .= $this->showTitles( $toSubscribe );
154 if ( $toUnsubscribe ) {
155 $successMessage .= Html::element(
158 $this->msg(
'tpt-manage-message-group-subscriptions-raw-removed' )
159 ->numParams( count( $toUnsubscribe ) )
162 $successMessage .= $this->showTitles( $toUnsubscribe );
165 $this->getOutput()->addHTML( $successMessage );
170 private function showTitles( array $messageGroupsIds ): string {
171 if ( count( $messageGroupsIds ) >= 100 ) {
172 return $this->msg(
'tpt-manage-message-group-subscriptions-too-many' )->parse();
177 $linkRenderer = $this->getLinkRenderer();
178 foreach ( $messageGroupsIds as $messageGroupId ) {
179 if ( $messageGroupId ===
"" ) {
183 $messageGroup = MessageGroups::getGroup( $messageGroupId );
184 if ( !$messageGroup ) {
185 $output .= Html::element(
'li', [], $messageGroupId ) .
"\n";
190 $linkRenderer->makeKnownLink(
191 SpecialPage::getTitleFor(
'Translate' ),
192 $messageGroup->getLabel(),
195 'group' => $messageGroupId,
201 $output .=
"</ul>\n";
211 private function getMessageGroupSubscriptionInfo(): array {
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;
223 $relatedPage = $messageGroup->getRelatedPage();
224 $namespace = $relatedPage ? $relatedPage->getNamespace() : $messageGroup->getNamespace();
226 $groupLabel = $messageGroup->getLabel();
227 $labels[$namespace][$groupLabel] = $messageGroup;
232 public function submitNormal( array $data ): bool {
235 foreach ( $data as $messageGroups ) {
237 if ( is_array( $messageGroups ) ) {
238 $toRemove = array_merge( $toRemove, $messageGroups );
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 ) )
247 $successMessage .= $this->showTitles( $toRemove );
248 $this->getOutput()->addHTML( $successMessage );
256 private function getNormalForm(): HTMLForm {
261 $subscriptionInfo = $this->getMessageGroupSubscriptionInfo();
263 foreach ( $subscriptionInfo as $namespace => $messageGroups ) {
265 foreach ( $messageGroups as $messageGroup ) {
266 if ( is_string( $messageGroup ) ) {
267 $options[htmlspecialchars( $messageGroup )] = $messageGroup;
269 $text = $this->buildRemoveLine( $messageGroup );
270 $options[$text] = $messageGroup->getId();
276 if ( count( $options ) > 0 ) {
278 $fields[
'CheckAllNs' . $namespace] = [
279 'cssclass' =>
'tpt-manage-subscriptions-messagegroups-checkall',
281 'section' =>
"ns$namespace",
282 'label' => $this->msg(
'tpt-manage-message-group-subscriptions-normal-check-all' )->text()
285 $fields[
'TitlesNs' . $namespace] = [
286 'cssclass' =>
'tpt-manage-message-group-subscriptions-messagegroups-check',
287 'class' => EditWatchlistCheckboxSeriesField::class,
288 'options' => $options,
289 'section' =>
"ns$namespace",
294 $form =
new EditWatchlistNormalHTMLForm( $fields, $this->getContext() );
295 $form->setTitle( $this->getPageTitle() );
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' ] );
307 private function buildRemoveLine(
MessageGroup $messageGroup ): string {
308 return $this->getLinkRenderer()->makeKnownLink(
309 SpecialPage::getTitleFor(
'Translate' ),
310 $messageGroup->getLabel(),
313 'group' => $messageGroup->getId(),
319 private function getRawForm(): HTMLForm {
320 $messageGroupIds = $this->messageGroupSubscription->getUserSubscriptions( $this->getUser() );
321 $labels = implode(
"\n", $messageGroupIds );
325 'type' =>
'textarea',
326 'label-message' =>
'tpt-manage-message-group-subscriptions-raw-titles',
327 'default' => $labels,
330 $form =
new OOUIHTMLForm( $fields, $this->getContext() );
331 $form->setTitle( $this->getPageTitle(
'raw' ) );
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' ] );
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