lbFactory = $lbFactory; $this->hookRunner = new HookRunner( $hookContainer ); $this->htmlCacheUpdater = $htmlCacheUpdater; $this->revisionStore = $revisionStore; } public function getType() { return 'revision'; } public static function getRelationType() { return 'rev_id'; } public static function getRestriction() { return 'deleterevision'; } public static function getRevdelConstant() { return RevisionRecord::DELETED_TEXT; } public static function suggestTarget( $target, array $ids ) { $revisionRecord = MediaWikiServices::getInstance() ->getRevisionLookup() ->getRevisionById( $ids[0] ); if ( $revisionRecord ) { return Title::newFromPageIdentity( $revisionRecord->getPage() ); } return $target; } /** * @param \Wikimedia\Rdbms\IReadableDatabase $db * @return IResultWrapper */ public function doQuery( $db ) { $ids = array_map( 'intval', $this->ids ); $queryBuilder = $this->revisionStore->newSelectQueryBuilder( $db ) ->joinComment() ->joinUser() ->joinPage() ->where( [ 'rev_page' => $this->page->getId(), 'rev_id' => $ids ] ) ->orderBy( 'rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC ) // workaround for MySQL bug (T104313) ->useIndex( [ 'revision' => 'PRIMARY' ] ); MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'revision' ); $live = $queryBuilder->caller( __METHOD__ )->fetchResultSet(); if ( $live->numRows() >= count( $ids ) ) { // All requested revisions are live, keeps things simple! return $live; } $queryBuilder = $this->revisionStore->newArchiveSelectQueryBuilder( $db ) ->joinComment() ->where( [ 'ar_rev_id' => $ids ] ) ->orderBy( 'ar_rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC ); MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'archive' ); // Check if any requested revisions are available fully deleted. $archived = $queryBuilder->caller( __METHOD__ )->fetchResultSet(); if ( $archived->numRows() == 0 ) { return $live; } elseif ( $live->numRows() == 0 ) { return $archived; } else { // Combine the two! Whee $rows = []; foreach ( $live as $row ) { $rows[$row->rev_id] = $row; } foreach ( $archived as $row ) { $rows[$row->ar_rev_id] = $row; } krsort( $rows ); return new FakeResultWrapper( array_values( $rows ) ); } } public function newItem( $row ) { if ( isset( $row->rev_id ) ) { return new RevDelRevisionItem( $this, $row ); } elseif ( isset( $row->ar_rev_id ) ) { return new RevDelArchivedRevisionItem( $this, $row, $this->lbFactory ); } else { // This shouldn't happen. :) throw new InvalidArgumentException( 'Invalid row type in RevDelRevisionList' ); } } public function getCurrent() { if ( $this->currentRevId === null ) { $dbw = $this->lbFactory->getPrimaryDatabase(); $this->currentRevId = $dbw->newSelectQueryBuilder() ->select( 'page_latest' ) ->from( 'page' ) ->where( [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ] ) ->caller( __METHOD__ )->fetchField(); } return $this->currentRevId; } public function doPreCommitUpdates() { Title::newFromPageIdentity( $this->page )->invalidateCache(); return Status::newGood(); } public function doPostCommitUpdates( array $visibilityChangeMap ) { $this->htmlCacheUpdater->purgeTitleUrls( $this->page, HTMLCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED ); // Extensions that require referencing previous revisions may need this $this->hookRunner->onArticleRevisionVisibilitySet( Title::newFromPageIdentity( $this->page ), $this->ids, $visibilityChangeMap ); return Status::newGood(); } }