Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
RenderTranslationPageJob.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\PageTranslation;
5
6use MediaWiki\CommentStore\CommentStoreComment;
9use MediaWiki\MediaWikiServices;
10use MediaWiki\Revision\SlotRecord;
11use MediaWiki\User\UserIdentity;
12use MediaWiki\User\UserRigorOptions;
13use RecentChange;
14use Title;
15use User;
16
24 public const ACTION_DELETE = 'delete';
25
26 public static function newJob(
27 Title $target,
28 ?string $triggerAction = null,
29 ?string $unitTitleText = null
30 ): self {
31 $job = new self( $target, [ 'triggerAction' => $triggerAction, 'unitTitle' => $unitTitleText ] );
32 $job->setUser( FuzzyBot::getUser() );
33 $job->setFlags( EDIT_FORCE_BOT );
34 $job->setSummary( wfMessage( 'tpt-render-summary' )->inContentLanguage()->text() );
35
36 return $job;
37 }
38
39 public function __construct( Title $title, array $params = [] ) {
40 parent::__construct( 'RenderTranslationPageJob', $title, $params );
41 $this->removeDuplicates = true;
42 }
43
44 public function run(): bool {
45 $this->logJobStart();
46 $mwServices = MediaWikiServices::getInstance();
47 // We may be doing double wait here if this job was spawned by TranslationUpdateJob
48 $lb = $mwServices->getDBLoadBalancerFactory();
49 if ( !$lb->waitForReplication() ) {
50 $this->logWarning( 'Continuing despite replication lag' );
51 }
52
53 // Initialization
54 $title = $this->title;
55
56 $tpPage = TranslatablePage::getTranslationPageFromTitle( $title );
57 if ( !$tpPage ) {
58 $this->logError( 'Cannot render translation page!' );
59 return false;
60 }
61
62 // Other stuff
63 $user = $this->getUser();
64 $summary = $this->getSummary();
65 $flags = $this->getFlags();
66
67 // We should not re-create the translation page if a translation unit is being deleted
68 // because it is possible that the translation page may also be queued for deletion.
69 // Hence set the flag to EDIT_UPDATE and remove EDIT_NEW if its added
70 if ( $this->isDeleteTrigger() ) {
71 $flags = ( $flags | EDIT_UPDATE ) & ~EDIT_NEW;
72 }
73
74 // @todo FuzzyBot hack
75 Hooks::$allowTargetEdit = true;
76
77 if ( class_exists( CommentStoreComment::class ) ) {
78 $commentStoreComment = CommentStoreComment::newUnsavedComment( $summary );
79 } else {
80 // MW < 1.40
81 $commentStoreComment = \CommentStoreComment::newUnsavedComment( $summary );
82 }
83
84 $content = $tpPage->getPageContent( $mwServices->getParser() );
85
86 $pageUpdater = $mwServices->getWikiPageFactory()
87 ->newFromTitle( $title )
88 ->newPageUpdater( $user );
89 $pageUpdater->setContent( SlotRecord::MAIN, $content );
90
91 if ( $user->authorizeWrite( 'autopatrol', $title ) ) {
92 $pageUpdater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
93 }
94
95 $pageUpdater->addTag( 'translate-translation-pages' );
96 $pageUpdater->saveRevision( $commentStoreComment, $flags );
97 $status = $pageUpdater->getStatus();
98
99 if ( !$status->isGood() ) {
100 if ( $this->isDeleteTrigger() && $status->hasMessage( 'edit-gone-missing' ) ) {
101 $this->logInfo( 'Translation page missing with delete trigger' );
102 } else {
103 $this->logError(
104 'Error while editing content in page.',
105 [
106 'content' => $content->getTextForSummary(),
107 'errors' => $status->getErrors()
108 ]
109 );
110 }
111 }
112
113 $this->logInfo( 'Finished page edit operation' );
114 Hooks::$allowTargetEdit = false;
115
116 $this->logInfo( 'Finished TranslateRenderJob' );
117 return true;
118 }
119
120 public function setFlags( int $flags ): void {
121 $this->params['flags'] = $flags;
122 }
123
124 private function getFlags(): int {
125 return $this->params['flags'];
126 }
127
128 public function setSummary( string $summary ): void {
129 $this->params['summary'] = $summary;
130 }
131
133 public function getDeduplicationInfo(): array {
134 $info = parent::getDeduplicationInfo();
135 // Unit title is only passed for logging and should not be used for de-duplication
136 unset( $info['params']['unitTitle'] );
137 return $info;
138 }
139
140 private function getSummary(): string {
141 return $this->params['summary'];
142 }
143
145 public function setUser( $user ): void {
146 if ( $user instanceof UserIdentity ) {
147 $this->params['user'] = $user->getName();
148 } else {
149 $this->params['user'] = $user;
150 }
151 }
152
154 private function getUser(): User {
155 $userFactory = MediaWikiServices::getInstance()->getUserFactory();
156 return $userFactory->newFromName( $this->params['user'], UserRigorOptions::RIGOR_NONE );
157 }
158
159 private function isDeleteTrigger(): bool {
160 $triggerAction = $this->params['triggerAction'] ?? null;
161 return $triggerAction === self::ACTION_DELETE;
162 }
163
164 private function logJobStart(): void {
165 $unitTitleText = $this->params['unitTitle'] ?? null;
166 $logMessage = 'Starting TranslateRenderJob ';
167 if ( $unitTitleText ) {
168 $logMessage .= "trigged by $unitTitleText ";
169 }
170
171 if ( $this->isDeleteTrigger() ) {
172 $logMessage .= '- [deletion] ';
173 }
174
175 $this->logInfo( trim( $logMessage ) );
176 }
177}
return[ '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:ExternalMessageSourceStateImporter'=> static function(MediaWikiServices $services):ExternalMessageSourceStateImporter { return new ExternalMessageSourceStateImporter($services->getMainConfig(), $services->get( 'Translate:GroupSynchronizationCache'), $services->getJobQueueGroup(), LoggerFactory::getInstance( 'Translate.GroupSynchronization'), $services->get( 'Translate:MessageIndex'));}, '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:HookRunner'=> static function(MediaWikiServices $services):HookRunner { return new HookRunner( $services->getHookContainer());}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore($services->get( 'Translate:RevTagStore'), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'));}, 'Translate:MessageGroupReviewStore'=> static function(MediaWikiServices $services):MessageGroupReviewStore { return new MessageGroupReviewStore($services->getDBLoadBalancer(), $services->get( 'Translate:HookRunner'));}, 'Translate:MessageGroupStatsTableFactory'=> static function(MediaWikiServices $services):MessageGroupStatsTableFactory { return new MessageGroupStatsTableFactory($services->get( 'Translate:ProgressStatsTableFactory'), $services->getDBLoadBalancer(), $services->getLinkRenderer(), $services->get( 'Translate:MessageGroupReviewStore'), $services->getMainConfig() ->get( 'TranslateWorkflowStates') !==false);}, 'Translate:MessageIndex'=> static function(MediaWikiServices $services):MessageIndex { $params=$services->getMainConfig() ->get( 'TranslateMessageIndex');if(is_string( $params)) { $params=(array) $params;} $class=array_shift( $params);return new $class( $params);}, '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->getDBLoadBalancer(), $services->getJsonCodec());}, 'Translate:ProgressStatsTableFactory'=> static function(MediaWikiServices $services):ProgressStatsTableFactory { return new ProgressStatsTableFactory($services->getLinkRenderer(), $services->get( 'Translate:ConfigHelper'));}, 'Translate:RevTagStore'=> static function(MediaWikiServices $services):RevTagStore { return new RevTagStore($services->getDBLoadBalancerFactory());}, 'Translate:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleExporter'=> static function(MediaWikiServices $services):TranslatableBundleExporter { return new TranslatableBundleExporter($services->get( 'Translate:SubpageListBuilder'), $services->getWikiExporterFactory(), $services->getDBLoadBalancer());}, '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());}, '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->getMainConfig() ->get( 'TranslatePageMoveLimit'));}, 'Translate:TranslatableBundleStatusStore'=> static function(MediaWikiServices $services):TranslatableBundleStatusStore { return new TranslatableBundleStatusStore($services->getDBLoadBalancer() ->getConnection(DB_PRIMARY), $services->getCollationFactory() ->makeCollation( 'uca-default-u-kn'), $services->getDBLoadBalancer() ->getMaintenanceConnectionRef(DB_PRIMARY));}, 'Translate:TranslatablePageParser'=> static function(MediaWikiServices $services):TranslatablePageParser { return new TranslatablePageParser($services->get( 'Translate:ParsingPlaceholderFactory'));}, 'Translate:TranslatablePageStore'=> static function(MediaWikiServices $services):TranslatablePageStore { return new TranslatablePageStore($services->get( 'Translate:MessageIndex'), $services->getJobQueueGroup(), $services->get( 'Translate:RevTagStore'), $services->getDBLoadBalancer(), $services->get( 'Translate:TranslatableBundleStatusStore'), $services->get( 'Translate:TranslatablePageParser'),);}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { $db=$services->getDBLoadBalancer() ->getConnection(DB_REPLICA);return new TranslationStashStorage( $db);}, 'Translate:TranslationStatsDataProvider'=> static function(MediaWikiServices $services):TranslationStatsDataProvider { return new TranslationStatsDataProvider(new ServiceOptions(TranslationStatsDataProvider::CONSTRUCTOR_OPTIONS, $services->getMainConfig()), $services->getObjectFactory(), $services->getDBLoadBalancer());}, '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);}]
@phpcs-require-sorted-array
Job for updating translation pages when translation or template changes.
FuzzyBot - the misunderstood workhorse.
Definition FuzzyBot.php:15