33 private JobQueueGroup $jobQueue;
35 private IConnectionProvider $dbProvider;
40 public function __construct(
42 JobQueueGroup $jobQueue,
44 IConnectionProvider $dbProvider,
49 $this->messageIndex = $messageIndex;
50 $this->jobQueue = $jobQueue;
51 $this->revTagStore = $revTagStore;
52 $this->dbProvider = $dbProvider;
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->dbProvider->getPrimaryDatabase();
103 $dbw->newDeleteQueryBuilder()
104 ->deleteFrom(
'translate_sections' )
105 ->where( [
'trs_page' => $title->getArticleID() ] )
106 ->caller( __METHOD__ )
113 public function unmark( PageIdentity $title ): void {
115 foreach ( $translatablePage->getTranslationPages() as $page ) {
116 $page->invalidateCache();
120 $this->messageGroupMetadata->clearMetadata( $groupId, TranslatablePage::METADATA_KEYS );
121 $this->removeFromAggregateGroups( $groupId );
126 $this->translatableBundleStatusStore->removeStatus( $title->getId() );
128 MessageGroups::singleton()->recache();
129 $this->jobQueue->push( RebuildMessageIndexJob::newJob( __METHOD__ ) );
131 TranslatablePage::clearSourcePageCache();
132 $translatablePage->getTitle()->invalidateCache();
137 DeferredUpdates::addCallableUpdate(
138 function () use ( $title ) {
139 $this->updateStatus( $title );
145 public function updateStatus( Title $title ): ?TranslatableBundleStatus {
146 $revTags = $this->revTagStore->getLatestRevisionsForTags(
152 $status = TranslatablePage::determineStatus(
153 $revTags[RevTagStore::TP_READY_TAG] ??
null,
154 $revTags[RevTagStore::TP_MARK_TAG] ??
null,
155 $title->getLatestRevID( IDBAccessObject::READ_LATEST )
159 $this->translatableBundleStatusStore->setStatus(
162 TranslatablePage::class
169 private function moveMetadata(
string $oldGroupId,
string $newGroupId ): void {
172 $this->messageGroupMetadata->preloadGroups( array_keys( $aggregateGroups ), __METHOD__ );
174 foreach ( $aggregateGroups as $id => $group ) {
175 $subgroups = $this->messageGroupMetadata->get( $id,
'subgroups' );
176 if ( $subgroups ===
false ) {
180 $subgroups = explode(
',', $subgroups );
181 $subgroups = array_flip( $subgroups );
182 if ( isset( $subgroups[$oldGroupId] ) ) {
183 $subgroups[$newGroupId] = $subgroups[$oldGroupId];
184 unset( $subgroups[$oldGroupId] );
185 $subgroups = array_flip( $subgroups );
186 $this->messageGroupMetadata->set(
189 implode(
',', $subgroups )
195 $priority = MessageGroups::getPriority( $oldGroupId );
196 if ( $priority !==
'' ) {
197 MessageGroups::setPriority( $newGroupId, $priority );
198 MessageGroups::setPriority( $oldGroupId,
'' );
202 private function removeFromAggregateGroups(
string $groupId ): void {
205 $this->messageGroupMetadata->preloadGroups( array_keys( $aggregateGroups ), __METHOD__ );
206 foreach ( $aggregateGroups as $group ) {
207 $subgroups = $this->messageGroupMetadata->get( $group->getId(),
'subgroups' );
208 if ( $subgroups !==
false ) {
209 $subgroups = explode(
',', $subgroups );
210 $subgroups = array_flip( $subgroups );
211 if ( isset( $subgroups[$groupId] ) ) {
212 unset( $subgroups[$groupId] );
213 $subgroups = array_flip( $subgroups );
214 $this->messageGroupMetadata->set(
217 implode(
',', $subgroups )