33 private JobQueueGroup $jobQueue;
35 private ILoadBalancer $loadBalancer;
40 public function __construct(
42 JobQueueGroup $jobQueue,
44 ILoadBalancer $loadBalancer,
49 $this->messageIndex = $messageIndex;
50 $this->jobQueue = $jobQueue;
51 $this->revTagStore = $revTagStore;
52 $this->loadBalancer = $loadBalancer;
53 $this->translatableBundleStatusStore = $translatableBundleStatusStore;
54 $this->translatablePageParser = $translatablePageParser;
55 $this->messageGroupMetadata = $messageGroupMetadata;
58 public function move( Title $oldName, Title $newName ):
void {
59 $oldTranslatablePage = TranslatablePage::newFromTitle( $oldName );
60 $newTranslatablePage = TranslatablePage::newFromTitle( $newName );
61 $oldGroupId = $oldTranslatablePage->getMessageGroupId();
62 $newGroupId = $newTranslatablePage->getMessageGroupId();
64 $this->messageGroupMetadata->moveMetadata( $oldGroupId, $newGroupId, TranslatablePage::METADATA_KEYS );
66 $this->moveMetadata( $oldGroupId, $newGroupId );
68 TranslatablePage::clearSourcePageCache();
71 MessageGroups::singleton()->recache();
74 $this->messageIndex->rebuild();
76 $job = UpdateTranslatablePageJob::newFromPage( TranslatablePage::newFromTitle( $newName ) );
77 $this->jobQueue->push( $job );
80 public function handleNullRevisionInsert(
TranslatableBundle $bundle, RevisionRecord $revision ):
void {
82 throw new InvalidArgumentException(
83 'Expected $bundle to be of type TranslatablePage, got ' . get_class( $bundle )
87 $pageContent = $revision->getContent( SlotRecord::MAIN );
88 if ( !$pageContent instanceof TextContent ) {
89 throw new RuntimeException(
"Translatable page {$bundle->getTitle()} has non-textual content." );
93 $pageText = $pageContent->getText();
94 if ( $this->translatablePageParser->containsMarkup( $pageText ) ) {
96 TranslatablePage::clearSourcePageCache();
101 public function delete( Title $title ): void {
102 $dbw = $this->loadBalancer->getConnection( DB_PRIMARY );
103 $dbw->delete(
'translate_sections', [
'trs_page' => $title->getArticleID() ], __METHOD__ );
109 public function unmark( PageIdentity $title ): void {
111 $translatablePage->getTranslationPercentages();
112 foreach ( $translatablePage->getTranslationPages() as $page ) {
113 $page->invalidateCache();
116 $groupId = $translatablePage->getMessageGroupId();
117 $this->messageGroupMetadata->clearMetadata( $groupId, TranslatablePage::METADATA_KEYS );
118 $this->removeFromAggregateGroups( $groupId );
123 $this->translatableBundleStatusStore->removeStatus( $title->getId() );
125 MessageGroups::singleton()->recache();
126 $this->jobQueue->push( RebuildMessageIndexJob::newJob( __METHOD__ ) );
128 TranslatablePage::clearSourcePageCache();
129 $translatablePage->getTitle()->invalidateCache();
134 DeferredUpdates::addCallableUpdate(
135 function () use ( $title ) {
136 $this->updateStatus( $title );
142 public function updateStatus( Title $title ): ?TranslatableBundleStatus {
143 $revTags = $this->revTagStore->getLatestRevisionsForTags(
149 $status = TranslatablePage::determineStatus(
150 $revTags[RevTagStore::TP_READY_TAG] ??
null,
151 $revTags[RevTagStore::TP_MARK_TAG] ??
null,
152 $title->getLatestRevID( IDBAccessObject::READ_LATEST )
156 $this->translatableBundleStatusStore->setStatus(
157 $title, $status, TranslatablePage::class
164 private function moveMetadata(
string $oldGroupId,
string $newGroupId ): void {
167 $this->messageGroupMetadata->preloadGroups( array_keys( $aggregateGroups ), __METHOD__ );
169 foreach ( $aggregateGroups as $id => $group ) {
170 $subgroups = $this->messageGroupMetadata->get( $id,
'subgroups' );
171 if ( $subgroups ===
false ) {
175 $subgroups = explode(
',', $subgroups );
176 $subgroups = array_flip( $subgroups );
177 if ( isset( $subgroups[$oldGroupId] ) ) {
178 $subgroups[$newGroupId] = $subgroups[$oldGroupId];
179 unset( $subgroups[$oldGroupId] );
180 $subgroups = array_flip( $subgroups );
181 $this->messageGroupMetadata->set(
184 implode(
',', $subgroups )
190 $priority = MessageGroups::getPriority( $oldGroupId );
191 if ( $priority !==
'' ) {
192 MessageGroups::setPriority( $newGroupId, $priority );
193 MessageGroups::setPriority( $oldGroupId,
'' );
197 private function removeFromAggregateGroups(
string $groupId ): void {
200 $this->messageGroupMetadata->preloadGroups( array_keys( $aggregateGroups ), __METHOD__ );
201 foreach ( $aggregateGroups as $group ) {
202 $subgroups = $this->messageGroupMetadata->get( $group->getId(),
'subgroups' );
203 if ( $subgroups !==
false ) {
204 $subgroups = explode(
',', $subgroups );
205 $subgroups = array_flip( $subgroups );
206 if ( isset( $subgroups[$groupId] ) ) {
207 unset( $subgroups[$groupId] );
208 $subgroups = array_flip( $subgroups );
209 $this->messageGroupMetadata->set(
212 implode(
',', $subgroups )