24 use Wikimedia\Timestamp\TimestampException;
73 $firstDestTimestamp = $this->dbw->selectField(
76 [
'rev_page' => $this->dest->getArticleID() ],
79 $this->maxTimestamp =
new MWTimestamp( $firstDestTimestamp );
87 $lastWorkingTimestamp = $this->dbw->selectField(
92 $this->dbw->addQuotes( $this->dbw->timestamp( $mwTimestamp ) ),
93 'rev_page' => $this->source->getArticleID()
97 $mwLastWorkingTimestamp =
new MWTimestamp( $lastWorkingTimestamp );
99 $timeInsert = $mwLastWorkingTimestamp;
100 $this->timestampLimit = $mwLastWorkingTimestamp;
106 $lastSourceTimestamp = $this->dbw->selectField(
107 [
'page',
'revision' ],
109 [
'page_id' => $this->source->getArticleID(),
110 'page_latest = rev_id'
114 $lasttimestamp =
new MWTimestamp( $lastSourceTimestamp );
117 $this->timestampLimit = $lasttimestamp;
120 $this->timeWhere =
"rev_timestamp <= " .
121 $this->dbw->addQuotes( $this->dbw->timestamp( $timeInsert ) );
122 }
catch ( TimestampException $ex ) {
125 $this->timestampLimit =
false;
134 $count = $this->dbw->selectRowCount(
'revision',
'1',
137 [
'LIMIT' => self::REVISION_LIMIT + 1 ]
163 $this->source->getUserPermissionsErrors(
'edit', $user ),
164 $this->dest->getUserPermissionsErrors(
'edit', $user )
169 foreach ( $errors as $error ) {
177 $status->fatal(
'spamprotectiontext' );
181 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
182 if ( !$permissionManager->userHasRight( $user,
'mergehistory' ) ) {
184 $status->fatal(
'mergehistory-fail-permission' );
201 if ( $this->source->getArticleID() === 0 ) {
202 $status->fatal(
'mergehistory-fail-invalid-source' );
204 if ( $this->dest->getArticleID() === 0 ) {
205 $status->fatal(
'mergehistory-fail-invalid-dest' );
209 if ( $this->source->equals( $this->dest ) ) {
210 $status->fatal(
'mergehistory-fail-self-merge' );
214 if ( !$this->timestampLimit ) {
215 $status->fatal(
'mergehistory-fail-bad-timestamp' );
219 if ( $this->timestampLimit > $this->maxTimestamp ) {
220 $status->fatal(
'mergehistory-fail-timestamps-overlap' );
224 if ( $this->timestampLimit && $this->
getRevisionCount() > self::REVISION_LIMIT ) {
225 $status->fatal(
'mergehistory-fail-toobig', Message::numParam( self::REVISION_LIMIT ) );
250 if ( !$validCheck->isOK() ) {
254 if ( !$permCheck->isOK() ) {
258 $this->dbw->startAtomic( __METHOD__ );
262 [
'rev_page' => $this->dest->getArticleID() ],
268 $this->revisionsMerged = $this->dbw->affectedRows();
269 if ( $this->revisionsMerged < 1 ) {
270 $this->dbw->endAtomic( __METHOD__ );
271 $status->fatal(
'mergehistory-fail-no-change' );
278 'revision_actor_temp',
279 [
'revactor_page' => $this->dest->getArticleID() ],
281 'revactor_page' => $this->source->getArticleID(),
283 str_replace(
'rev_timestamp',
'revactor_timestamp', $this->timeWhere )
289 $haveRevisions = $this->dbw->lockForUpdate(
291 [
'rev_page' => $this->source->getArticleID() ],
294 if ( !$haveRevisions ) {
297 'mergehistory-comment',
298 $this->source->getPrefixedText(),
299 $this->dest->getPrefixedText(),
301 )->inContentLanguage()->text();
304 'mergehistory-autocomment',
305 $this->source->getPrefixedText(),
306 $this->dest->getPrefixedText()
307 )->inContentLanguage()->text();
311 $redirectContent = $contentHandler->makeRedirectContent(
313 wfMessage(
'mergehistory-redirect-text' )->inContentLanguage()->plain()
316 if ( $redirectContent ) {
319 'title' => $this->source,
320 'page' => $this->source->getArticleID(),
321 'comment' => $reason,
322 'content' => $redirectContent ] );
323 $redirectRevision->
insertOn( $this->dbw );
324 $redirectPage->updateRevisionOn( $this->dbw, $redirectRevision );
330 [
'pl_from' => $this->dest->getArticleID() ],
333 $this->dbw->insert(
'pagelinks',
335 'pl_from' => $this->dest->getArticleID(),
336 'pl_from_namespace' => $this->dest->getNamespace(),
337 'pl_namespace' => $this->dest->getNamespace(),
338 'pl_title' => $this->dest->getDBkey() ],
343 $status->warning(
'mergehistory-warning-redirect-not-created' );
346 $this->source->invalidateCache();
348 $this->dest->invalidateCache();
351 $store = MediaWikiServices::getInstance()->getWatchedItemStore();
352 $store->duplicateAllAssociatedEntries( $this->source, $this->dest );
356 $logEntry->setPerformer( $user );
357 $logEntry->setComment( $reason );
358 $logEntry->setTarget( $this->source );
359 $logEntry->setParameters( [
360 '4::dest' => $this->dest->getPrefixedText(),
361 '5::mergepoint' => $this->timestampLimit->getTimestamp( TS_MW )
363 $logId = $logEntry->insert();
364 $logEntry->publish( $logId );
366 Hooks::run(
'ArticleMergeComplete', [ $this->source, $this->dest ] );
368 $this->dbw->endAtomic( __METHOD__ );