Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
MoveTranslatableBundleSpecialPage.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\PageTranslation;
5
6use InvalidArgumentException;
7use MediaWiki\CommentStore\CommentStore;
11use MediaWiki\Html\Html;
12use MediaWiki\HTMLForm\HTMLForm;
13use MediaWiki\Language\FormatterFactory;
14use MediaWiki\Message\Message;
15use MediaWiki\Output\OutputPage;
16use MediaWiki\Permissions\PermissionManager;
17use MediaWiki\Permissions\PermissionStatus;
18use MediaWiki\SpecialPage\UnlistedSpecialPage;
19use MediaWiki\Title\Title;
20use PermissionsError;
21use SplObjectStorage;
22use ThrottledError;
23use Wikimedia\ObjectFactory\ObjectFactory;
24
33class MoveTranslatableBundleSpecialPage extends UnlistedSpecialPage {
34 // Form parameters both as text and as titles
35 private string $oldText;
36 private string $reason;
37 private bool $moveTalkpages = true;
38 private bool $moveSubpages = true;
39 private bool $leaveRedirect = true;
40 private ObjectFactory $objectFactory;
41 private TranslatableBundleMover $bundleMover;
42 private PermissionManager $permissionManager;
43 private TranslatableBundleFactory $bundleFactory;
44 private FormatterFactory $formatterFactory;
46 private $movePageSpec;
47 // Other
48 private ?Title $oldTitle;
49
58 public function __construct(
59 ObjectFactory $objectFactory,
60 PermissionManager $permissionManager,
61 TranslatableBundleMover $bundleMover,
62 TranslatableBundleFactory $bundleFactory,
63 FormatterFactory $formatterFactory,
64 $movePageSpec
65 ) {
66 parent::__construct( 'Movepage' );
67 $this->objectFactory = $objectFactory;
68 $this->permissionManager = $permissionManager;
69 $this->bundleMover = $bundleMover;
70 $this->bundleFactory = $bundleFactory;
71 $this->formatterFactory = $formatterFactory;
72 $this->movePageSpec = $movePageSpec;
73 }
74
76 public function doesWrites(): bool {
77 return true;
78 }
79
80 protected function getGroupName(): string {
81 return 'pagetools';
82 }
83
85 public function execute( $par ) {
86 $request = $this->getRequest();
87
88 $this->oldText = $request->getText(
89 'wpOldTitle',
90 $request->getText( 'target', $par ?? '' )
91 );
92
93 $this->oldTitle = Title::newFromText( $this->oldText );
94
95 if ( $this->oldTitle == null ) {
96 // Not a valid title at all. Let core MovePage display the validation error to ensure consistency
97 $this->objectFactory->createObject( $this->movePageSpec )->execute( $par );
98 return;
99 }
100 $bundle = $this->bundleFactory->getBundle( $this->oldTitle );
101 if ( !$bundle || !$bundle->isMoveable() ) {
102 // Not a translatable page. Let core MovePage handle it
103 $this->objectFactory->createObject( $this->movePageSpec )->execute( $par );
104 return;
105 }
106 // Now we know we're actually moving a translatable page
107 $newText = $request->getText( 'wpNewTitle' );
108 $user = $this->getUser();
109 $out = $this->getOutput();
110 $out->addModuleStyles( [
111 'ext.translate.special.movetranslatablebundles.styles',
112 'mediawiki.codex.messagebox.styles',
113 ] );
114
115 $newTitle = Title::newFromText( $newText );
116 // Normalize input
117 if ( $this->oldTitle ) {
118 $this->oldText = $this->oldTitle->getPrefixedText();
119 }
120
121 $this->reason = $request->getText( 'reason' );
122
123 $this->addHelpLink( 'Help:Extension:Translate/Move_translatable_page' );
124
125 // Since MW 1.36, Authority should be used to check permissions
126 $status = PermissionStatus::newEmpty();
127 if ( !$this->getAuthority()
128 ->definitelyCan( 'move', $this->oldTitle, $status )
129 ) {
130 throw new PermissionsError( 'move', $status );
131 }
132
133 $this->getOutput()->setPageTitleMsg( $this->getSpecialPageTitle( $bundle ) );
134
135 if ( !$user->isAllowed( 'pagetranslation' ) ) {
136 throw new PermissionsError( 'pagetranslation' );
137 }
138
139 $subaction = $this->getSubactionFromRequest( $request->getText( 'subaction' ) );
140
141 $isValidPostRequest = $this->checkToken() && $request->wasPosted();
142 if ( $isValidPostRequest && $subaction === 'check' ) {
143 try {
144 $pageCollection = $this->bundleMover->getPageMoveCollection(
145 $this->oldTitle,
146 $newTitle,
147 $user,
148 $this->reason,
149 $this->moveSubpages,
150 $this->moveTalkpages,
151 $this->leaveRedirect
152 );
153 } catch ( ImpossiblePageMove $e ) {
154 $this->showErrors( $e->getBlockers() );
155 $this->showForm( $bundle );
156 return;
157 }
158
159 $this->showConfirmation( $pageCollection, $bundle );
160 } elseif ( $isValidPostRequest && $subaction === 'perform' ) {
161 $this->moveSubpages = $request->getBool( 'subpages' );
162 $this->moveTalkpages = $request->getBool( 'talkpages' );
163 $this->leaveRedirect = $request->getBool( 'redirect' );
164
165 // This will throw exceptions if there is an error.
166 $this->authorizeMove();
167
168 $this->bundleMover->moveAsynchronously(
169 $this->oldTitle,
170 $newTitle,
171 $this->moveSubpages,
172 $this->getUser(),
173 $this->reason,
174 $this->moveTalkpages,
175 $this->leaveRedirect,
176 $this->getContext()->exportSession()
177 );
178 $this->getOutput()->addWikiMsg(
179 'pt-movepage-started',
180 $this->getLogPageWikiLink( $this->bundleFactory->getValidBundle( $this->oldTitle ) )
181 );
182 } else {
183 $this->showForm( $bundle );
184 }
185 }
186
188 protected function authorizeMove(): void {
189 $status = PermissionStatus::newEmpty();
190 $this->getAuthority()
191 ->authorizeWrite( 'move', $this->oldTitle, $status );
192
193 if ( !$status->isOK() ) {
194 if ( $status->isRateLimitExceeded() ) {
195 throw new ThrottledError;
196 } else {
197 throw new PermissionsError( 'move', $status );
198 }
199 }
200 }
201
203 protected function checkToken(): bool {
204 return $this->getContext()->getCsrfTokenSet()->matchTokenField( 'wpEditToken' );
205 }
206
208 protected function showErrors( SplObjectStorage $errors ): void {
209 // If there are many errors, for performance reasons we must parse them all at once
210 $s = '';
211 $context = 'pt-movepage-error-placeholder';
212 foreach ( $errors as $title ) {
213 $titleText = $title->getPrefixedText();
214 $s .= "'''$titleText'''\n\n";
215 $s .= $errors[ $title ]->getWikiText( false, $context );
216 }
217
218 $out = $this->getOutput();
219 $out->addHTML(
220 Html::errorBox(
221 $out->msg(
222 'pt-movepage-blockers',
223 $this->getLanguage()->formatNum( count( $errors ) )
224 )->parseAsBlock() .
225 $out->parseAsContent( $s )
226 )
227 );
228 }
229
231 public function showForm( TranslatableBundle $bundle ) {
232 $this->getOutput()->addBacklinkSubtitle( $this->oldTitle );
233 $this->getOutput()->addWikiMsg(
234 'pt-movepage-intro',
235 $this->getLogPageWikiLink(
236 $this->bundleFactory->getBundle( Title::newFromText( $this->oldText ) )
237 )
238 );
239
240 HTMLForm::factory( 'ooui', $this->getCommonFormFields(), $this->getContext() )
241 ->setMethod( 'post' )
242 ->setAction( $this->getPageTitle( $this->oldText )->getLocalURL() )
243 ->setSubmitName( 'subaction' )
244 ->setSubmitTextMsg( 'pt-movepage-action-check' )
245 ->setWrapperLegendMsg(
246 $bundle instanceof MessageBundle ? 'pt-movepage-messagebundle-legend' : 'pt-movepage-legend'
247 )
248 ->prepareForm()
249 ->displayForm( false );
250 }
251
256 protected function showConfirmation( PageMoveCollection $pageCollection, TranslatableBundle $bundle ): void {
257 $out = $this->getOutput();
258 $out->addBacklinkSubtitle( $this->oldTitle );
259 $out->addWikiMsg(
260 'pt-movepage-intro',
261 $this->getLogPageWikiLink(
262 $this->bundleFactory->getBundle( Title::newFromText( $this->oldText ) )
263 )
264 );
265
266 $count = 0;
267 $subpagesCount = 0;
268 $talkpagesCount = 0;
269
271 $pagesToMove = [
272 'pt-movepage-list-source' => [ $pageCollection->getTranslatablePage() ],
273 'pt-movepage-list-translation' => $pageCollection->getTranslationPagesPair(),
274 'pt-movepage-list-section' => $pageCollection->getUnitPagesPair()
275 ];
276
277 $subpages = $pageCollection->getSubpagesPair();
278 if ( $subpages ) {
279 $pagesToMove[ 'pt-movepage-list-other'] = $subpages;
280 }
281
282 $out->wrapWikiMsg( '== $1 ==', [ 'pt-movepage-list-pages' ] );
283
284 foreach ( $pagesToMove as $type => $pages ) {
285 $this->addSectionHeaderAndMessage( $out, $type, $pages );
286
287 if ( !$pages ) {
288 continue;
289 }
290
291 $lines = [];
292
293 foreach ( $pages as $pagePairs ) {
294 $count++;
295
296 if ( $type === 'pt-movepage-list-other' ) {
297 $subpagesCount++;
298 }
299
300 $old = $pagePairs->getOldTitle();
301 $new = $pagePairs->getNewTitle();
302 $line = '* ' . $old->getPrefixedText() . ' → ' . $new->getPrefixedText();
303 if ( $pagePairs->hasTalkpage() ) {
304 $count++;
305 $talkpagesCount++;
306 $line .= ' ' . $this->msg( 'pt-movepage-talkpage-exists' )->text();
307 }
308
309 $lines[] = $line;
310 }
311
312 $out->addWikiTextAsInterface( implode( "\n", $lines ) );
313 }
314
315 $nonMovableSubpages = $pageCollection->getNonMovableSubpages();
316 if ( $nonMovableSubpages ) {
317 $this->addSectionHeaderAndMessage( $out, 'pt-movepage-list-nonmovable', $nonMovableSubpages );
318 $lines = [];
319 $out->wrapWikiMsg( "'''$1'''", [ 'pt-movepage-list-nonmovable-note', count( $nonMovableSubpages ) ] );
320 foreach ( $nonMovableSubpages as $page => $status ) {
321 $invalidityReason = $this->formatterFactory
322 ->getStatusFormatter( $this->getContext() )
323 ->getWikiText( $status );
324 $lines[] = '* ' . $page . ' (' . str_replace( "\n", " ", $invalidityReason ) . ')';
325 }
326
327 $out->addWikiTextAsInterface( implode( "\n", $lines ) );
328 }
329
330 $translatableSubpages = $pageCollection->getTranslatableSubpages();
331 $sectionType = 'pt-movepage-list-translatable';
332 $this->addSectionHeaderAndMessage( $out, $sectionType, $translatableSubpages );
333 if ( $translatableSubpages ) {
334 $lines = [];
335 $out->wrapWikiMsg( "'''$1'''", $this->msg( 'pt-movepage-list-translatable-note' ) );
336 foreach ( $translatableSubpages as $page ) {
337 $lines[] = '* ' . $page->getPrefixedText();
338 }
339 $out->addWikiTextAsInterface( implode( "\n", $lines ) );
340 }
341
342 $out->addWikiTextAsInterface( "----\n" );
343 $out->addWikiMsg(
344 'pt-movepage-list-count',
345 $this->getLanguage()->formatNum( $count ),
346 $this->getLanguage()->formatNum( $subpagesCount ),
347 $this->getLanguage()->formatNum( $talkpagesCount )
348 );
349
350 $formDescriptor = array_merge(
351 $this->getCommonFormFields(),
352 [
353 'subpages' => [
354 'type' => 'check',
355 'name' => 'subpages',
356 'id' => 'mw-subpages',
357 'label-message' =>
358 count( $nonMovableSubpages ) ? 'pt-movepage-subpages-blocked-exist' : 'pt-movepage-subpages'
359 ],
360 'redirect' => [
361 'type' => 'check',
362 'name' => 'redirect',
363 'id' => 'mw-leave-redirect',
364 'label-message' => 'pt-leave-redirect',
365 'default' => $this->leaveRedirect,
366 ],
367 'talkpages' => [
368 'type' => 'check',
369 'name' => 'talkpages',
370 'id' => 'mw-talkpages',
371 'label-message' => 'pt-movepage-talkpages',
372 'default' => $this->moveTalkpages
373 ]
374 ]
375 );
376
377 $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
378 $htmlForm
379 ->addButton( [
380 'name' => 'subaction',
381 'value' => $this->msg( 'pt-movepage-action-other' )->text(),
382 ] )
383 ->setMethod( 'post' )
384 ->setAction( $this->getPageTitle( $this->oldText )->getLocalURL() )
385 ->setSubmitName( 'subaction' )
386 ->setSubmitTextMsg( 'pt-movepage-action-perform' )
387 ->setWrapperLegendMsg(
388 $bundle instanceof MessageBundle ? 'pt-movepage-messagebundle-legend' : 'pt-movepage-legend'
389 )
390 ->prepareForm()
391 ->displayForm( false );
392 }
393
395 private function addSectionHeaderAndMessage( OutputPage $out, string $type, array $pages ): void {
396 $leaveRedirect = TranslatableBundleMover::shouldLeaveRedirect( $type, $this->leaveRedirect );
397
398 $pageCount = count( $pages );
399 if ( $leaveRedirect ) {
400 $headingRedirectLabel = $this->msg(
401 'pt-leave-redirect-label',
402 $this->msg( $type, $pageCount )->text()
403 )->text();
404 $out->addWikiTextAsInterface( "<h3 class=\"mw-translate-leave-redirect\">$headingRedirectLabel</h3>" );
405 } else {
406 $out->wrapWikiMsg( '=== $1 ===', [ $type, $pageCount ] );
407 }
408
409 if ( !$pageCount ) {
410 $out->addWikiMsg( 'pt-movepage-list-no-pages' );
411 }
412 }
413
414 private function getSubactionFromRequest( string $subactionText ): string {
415 switch ( $subactionText ) {
416 case $this->msg( 'pt-movepage-action-check' )->text():
417 return 'check';
418 case $this->msg( 'pt-movepage-action-perform' )->text():
419 return 'perform';
420 case $this->msg( 'pt-movepage-action-other' )->text():
421 return 'show-form';
422 default:
423 return 'show-form';
424 }
425 }
426
427 private function getCommonFormFields(): array {
428 return [
429 'wpOldTitle' => [
430 'type' => 'text',
431 'name' => 'wpOldTitle',
432 'label-message' => 'pt-movepage-current',
433 'default' => $this->oldText,
434 'readonly' => true,
435 ],
436 'wpNewTitle' => [
437 'type' => 'text',
438 'name' => 'wpNewTitle',
439 'label-message' => 'pt-movepage-new',
440 ],
441 'reason' => [
442 'type' => 'text',
443 'name' => 'reason',
444 'label-message' => 'pt-movepage-reason',
445 'maxlength' => CommentStore::COMMENT_CHARACTER_LIMIT,
446 'default' => $this->reason,
447 ],
448 'redirect' => [
449 'type' => 'hidden',
450 'name' => 'redirect',
451 'id' => 'mw-leave-redirect',
452 'label-message' => 'pt-leave-redirect',
453 'default' => $this->leaveRedirect,
454 ],
455 'subpages' => [
456 'type' => 'hidden',
457 'name' => 'subpages',
458 'default' => $this->moveSubpages,
459 ],
460 'talkpages' => [
461 'type' => 'hidden',
462 'name' => 'talkpages',
463 'default' => $this->moveTalkpages
464 ]
465 ];
466 }
467
468 private function getSpecialPageTitle( TranslatableBundle $bundle ): Message {
469 if ( $bundle instanceof TranslatablePage ) {
470 return $this->msg( 'pt-movepage-title', $this->oldText );
471 } elseif ( $bundle instanceof MessageBundle ) {
472 return $this->msg( 'pt-movepage-messagebundle-title', $this->oldText );
473 }
474
475 throw new InvalidArgumentException( 'TranslatableBundle is neither a TranslatablePage or MessageBundle' );
476 }
477
478 private function getLogPageWikiLink( ?TranslatableBundle $bundle ): string {
479 if ( $bundle instanceof MessageBundle ) {
480 return 'Special:Log/messagebundle';
481 }
482
483 // Default to page translation log in case of errors
484 return 'Special:Log/pagetranslation';
485 }
486}
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
Create instances of various classes based on the type of TranslatableBundle.
Translatable bundle represents a message group where its translatable content is defined on a wiki pa...
Exception thrown when a translatable page move is not possible.
Replacement for Special:Movepage to allow renaming a translatable bundle and all pages associated wit...
__construct(ObjectFactory $objectFactory, PermissionManager $permissionManager, TranslatableBundleMover $bundleMover, TranslatableBundleFactory $bundleFactory, FormatterFactory $formatterFactory, $movePageSpec)
showConfirmation(PageMoveCollection $pageCollection, TranslatableBundle $bundle)
The second form, which still allows changing some things.
Collection of pages potentially affected by a page move operation.
getNonMovableSubpages()
Get list of subpages which cannot be moved for various reasons (e.g.
Contains the core logic to validate and move translatable bundles.