Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
RenderTranslationPageJob.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\PageTranslation;
5
6use 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 $commentStoreComment = CommentStoreComment::newUnsavedComment( $summary );
77 $content = $tpPage->getPageContent();
78
79 $pageUpdater = $mwServices->getWikiPageFactory()
80 ->newFromTitle( $title )
81 ->newPageUpdater( $user );
82 $pageUpdater->setContent( SlotRecord::MAIN, $content );
83
84 if ( $user->authorizeWrite( 'autopatrol', $title ) ) {
85 $pageUpdater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
86 }
87
88 $pageUpdater->saveRevision( $commentStoreComment, $flags );
89 $status = $pageUpdater->getStatus();
90
91 if ( !$status->isGood() ) {
92 if ( $this->isDeleteTrigger() && $status->hasMessage( 'edit-gone-missing' ) ) {
93 $this->logInfo( 'Translation page missing with delete trigger' );
94 } else {
95 $this->logError(
96 'Error while editing content in page.',
97 [
98 'content' => $content->getTextForSummary(),
99 'errors' => $status->getErrors()
100 ]
101 );
102 }
103 }
104
105 $this->logInfo( 'Finished page edit operation' );
106 Hooks::$allowTargetEdit = false;
107
108 $this->logInfo( 'Finished TranslateRenderJob' );
109 return true;
110 }
111
112 public function setFlags( int $flags ): void {
113 $this->params['flags'] = $flags;
114 }
115
116 private function getFlags(): int {
117 return $this->params['flags'];
118 }
119
120 public function setSummary( string $summary ): void {
121 $this->params['summary'] = $summary;
122 }
123
125 public function getDeduplicationInfo(): array {
126 $info = parent::getDeduplicationInfo();
127 // Unit title is only passed for logging and should not be used for de-duplication
128 unset( $info['params']['unitTitle'] );
129 return $info;
130 }
131
132 private function getSummary(): string {
133 return $this->params['summary'];
134 }
135
137 public function setUser( $user ): void {
138 if ( $user instanceof UserIdentity ) {
139 $this->params['user'] = $user->getName();
140 } else {
141 $this->params['user'] = $user;
142 }
143 }
144
146 private function getUser(): User {
147 $userFactory = MediaWikiServices::getInstance()->getUserFactory();
148 return $userFactory->newFromName( $this->params['user'], UserRigorOptions::RIGOR_NONE );
149 }
150
151 private function isDeleteTrigger(): bool {
152 $triggerAction = $this->params['triggerAction'] ?? null;
153 return $triggerAction === self::ACTION_DELETE;
154 }
155
156 private function logJobStart(): void {
157 $unitTitleText = $this->params['unitTitle'] ?? null;
158 $logMessage = 'Starting TranslateRenderJob ';
159 if ( $unitTitleText ) {
160 $logMessage .= "trigged by $unitTitleText ";
161 }
162
163 if ( $this->isDeleteTrigger() ) {
164 $logMessage .= '- [deletion] ';
165 }
166
167 $this->logInfo( trim( $logMessage ) );
168 }
169}
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'), MessageIndex::singleton());}, 'Translate:GroupSynchronizationCache'=> static function(MediaWikiServices $services):GroupSynchronizationCache { return new GroupSynchronizationCache( $services->get( 'Translate:PersistentCache'));}, 'Translate:MessageBundleStore'=> static function(MediaWikiServices $services):MessageBundleStore { return new MessageBundleStore(new RevTagStore(), $services->getJobQueueGroup(), $services->getLanguageNameUtils(), $services->get( 'Translate:MessageIndex'));}, 'Translate:MessageGroupReview'=> static function(MediaWikiServices $services):MessageGroupReview { return new MessageGroupReview($services->getDBLoadBalancer(), $services->getHookContainer());}, '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: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:SubpageListBuilder'=> static function(MediaWikiServices $services):SubpageListBuilder { return new SubpageListBuilder($services->get( 'Translate:TranslatableBundleFactory'), $services->getLinkBatchFactory());}, 'Translate:TranslatableBundleFactory'=> static function(MediaWikiServices $services):TranslatableBundleFactory { return new TranslatableBundleFactory($services->get( 'Translate:TranslatablePageStore'), $services->get( 'Translate:MessageBundleStore'));}, '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: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(), new RevTagStore(), $services->getDBLoadBalancer());}, 'Translate:TranslationStashReader'=> static function(MediaWikiServices $services):TranslationStashReader { $db=$services->getDBLoadBalancer() ->getConnectionRef(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());}, '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