214 $updater = $this->wikiPageFactory->newFromTitle( $this->page )->newPageUpdater( $this->performer );
215 $currentRevision = $updater->grabParentRevision();
217 if ( !$currentRevision ) {
219 return StatusValue::newFatal(
'notanarticle' );
222 $currentEditor = $currentRevision->getUser( RevisionRecord::RAW );
223 $currentEditorForPublic = $currentRevision->getUser( RevisionRecord::FOR_PUBLIC );
225 if ( !$this->byUser->equals( $currentEditor ) ) {
226 $result = StatusValue::newGood( [
227 'current-revision-record' => $currentRevision
231 htmlspecialchars( $this->titleFormatter->getPrefixedText( $this->page ) ),
232 htmlspecialchars( $this->byUser->getName() ),
233 htmlspecialchars( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' )
238 $dbw = $this->dbProvider->getPrimaryDatabase();
242 $actorWhere = $this->actorMigration->getWhere( $dbw,
'rev_user', $currentEditor );
244 ->where( [
'rev_page' => $currentRevision->getPageId(),
'NOT(' . $actorWhere[
'conds'] .
')' ] )
245 ->useIndex( [
'revision' =>
'rev_page_timestamp' ] )
246 ->orderBy( [
'rev_timestamp',
'rev_id' ], SelectQueryBuilder::SORT_DESC );
247 $targetRevisionRow = $queryBuilder->caller( __METHOD__ )->fetchRow();
249 if ( $targetRevisionRow ===
false ) {
251 return StatusValue::newFatal(
'cantrollback' );
252 } elseif ( $targetRevisionRow->rev_deleted & RevisionRecord::DELETED_TEXT
253 || $targetRevisionRow->rev_deleted & RevisionRecord::DELETED_USER
256 return StatusValue::newFatal(
'notvisiblerev' );
260 $targetRevision = $this->revisionStore
261 ->getRevisionById( $targetRevisionRow->rev_id, IDBAccessObject::READ_LATEST );
266 if ( $this->performer->isAllowed(
'minoredit' ) ) {
275 $currentContent = $currentRevision->getContent( SlotRecord::MAIN );
276 $targetContent = $targetRevision->getContent( SlotRecord::MAIN );
277 $changingContentModel = $targetContent->getModel() !== $currentContent->getModel();
282 foreach ( $targetRevision->getSlots()->getSlots() as $slot ) {
283 $updater->inheritSlot( $slot );
288 foreach ( $currentRevision->getSlotRoles() as $role ) {
289 if ( !$targetRevision->hasSlot( $role ) ) {
290 $updater->removeSlot( $role );
294 $updater->setCause( PageUpdateCauses::CAUSE_ROLLBACK );
295 $updater->markAsRevert(
296 EditResult::REVERT_ROLLBACK,
297 $currentRevision->getId(),
298 $targetRevision->getId()
304 if ( $this->options->get( MainConfigNames::UseRCPatrol ) &&
305 $this->performer->authorizeWrite(
'autopatrol', $this->page )
307 $updater->setRcPatrolStatus( RecentChange::PRC_AUTOPATROLLED );
310 $summary = $this->getSummary( $currentRevision, $targetRevision );
313 $rev = $updater->addTags( $this->tags )->saveRevision(
314 CommentStoreComment::newUnsavedComment( $summary ),
319 $this->updateRecentChange( $dbw, $currentRevision, $targetRevision );
321 if ( !$updater->wasSuccessful() ) {
322 return $updater->getStatus();
326 if ( !$updater->wasRevisionCreated() ) {
327 $result = StatusValue::newGood( [
328 'current-revision-record' => $currentRevision
332 htmlspecialchars( $this->titleFormatter->getPrefixedText( $this->page ) ),
333 htmlspecialchars( $this->byUser->getName() ),
334 htmlspecialchars( $currentEditorForPublic ? $currentEditorForPublic->getName() :
'' )
339 if ( $changingContentModel ) {
343 $log->setPerformer( $this->performer->getUser() );
344 $log->setTarget(
new TitleValue( $this->page->getNamespace(), $this->page->getDBkey() ) );
345 $log->setComment( $summary );
346 $log->setParameters( [
347 '4::oldmodel' => $currentContent->getModel(),
348 '5::newmodel' => $targetContent->getModel(),
351 $logId = $log->insert( $dbw );
352 $log->publish( $logId );
355 $wikiPage = $this->wikiPageFactory->newFromTitle( $this->page );
357 $this->hookRunner->onRollbackComplete(
359 $this->performer->getUser(),
364 return StatusValue::newGood( [
365 'summary' => $summary,
366 'current-revision-record' => $currentRevision,
367 'target-revision-record' => $targetRevision,
368 'newid' => $rev->getId(),
369 'tags' => array_merge( $this->tags, $updater->getEditResult()->getRevertTags() )