MediaWiki master
RevDelRevisionList.php
Go to the documentation of this file.
1<?php
9
10use InvalidArgumentException;
29
40
42 private $hookRunner;
43
46
47 public function __construct(
48 IContextSource $context,
50 array $ids,
51 private readonly LBFactory $lbFactory,
52 HookContainer $hookContainer,
53 private readonly HTMLCacheUpdater $htmlCacheUpdater,
54 private readonly RevisionStore $revisionStore,
55 private readonly DomainEventDispatcher $eventDispatcher,
56 private readonly ChangeTagsFormatter $changeTagsFormatter,
57 ) {
58 parent::__construct( $context, $page, $ids, $this->lbFactory );
59 $this->hookRunner = new HookRunner( $hookContainer );
60 }
61
63 public function getType() {
64 return 'revision';
65 }
66
68 public static function getRelationType() {
69 return 'rev_id';
70 }
71
73 public static function getRestriction() {
74 return 'deleterevision';
75 }
76
78 public static function getRevdelConstant() {
79 return RevisionRecord::DELETED_TEXT;
80 }
81
83 public static function suggestTarget( $target, array $ids ) {
84 $revisionRecord = MediaWikiServices::getInstance()
85 ->getRevisionLookup()
86 ->getRevisionById( $ids[0] );
87
88 if ( $revisionRecord ) {
89 return Title::newFromPageIdentity( $revisionRecord->getPage() );
90 }
91 return $target;
92 }
93
98 public function doQuery( $db ) {
99 $ids = array_map( 'intval', $this->ids );
100 $queryBuilder = $this->revisionStore->newSelectQueryBuilder( $db )
101 ->joinComment()
102 ->joinUser()
103 ->joinPage()
104 ->where( [ 'rev_page' => $this->page->getId(), 'rev_id' => $ids ] )
105 ->orderBy( 'rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC )
106 // workaround for MySQL bug (T104313)
107 ->useIndex( [ 'revision' => 'PRIMARY' ] );
108
109 MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'revision' );
110
111 $live = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
112 if ( $live->numRows() >= count( $ids ) ) {
113 // All requested revisions are live, keeps things simple!
114 return $live;
115 }
116
117 $queryBuilder = $this->revisionStore->newArchiveSelectQueryBuilder( $db )
118 ->joinComment()
119 ->where( [ 'ar_rev_id' => $ids ] )
120 ->orderBy( 'ar_rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC );
121
122 MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'archive' );
123
124 // Check if any requested revisions are available fully deleted.
125 $archived = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
126
127 if ( $archived->numRows() == 0 ) {
128 return $live;
129 } elseif ( $live->numRows() == 0 ) {
130 return $archived;
131 } else {
132 // Combine the two! Whee
133 $rows = [];
134 foreach ( $live as $row ) {
135 $rows[$row->rev_id] = $row;
136 }
137 foreach ( $archived as $row ) {
138 $rows[$row->ar_rev_id] = $row;
139 }
140 krsort( $rows );
141 return new FakeResultWrapper( array_values( $rows ) );
142 }
143 }
144
146 public function newItem( $row ) {
147 if ( isset( $row->rev_id ) ) {
148 return new RevDelRevisionItem( $this, $row, $this->changeTagsFormatter );
149 } elseif ( isset( $row->ar_rev_id ) ) {
150 return new RevDelArchivedRevisionItem( $this, $row, $this->lbFactory, $this->changeTagsFormatter );
151 } else {
152 // This shouldn't happen. :)
153 throw new InvalidArgumentException( 'Invalid row type in RevDelRevisionList' );
154 }
155 }
156
158 public function getCurrent() {
159 if ( $this->currentRevId === null ) {
160 $dbw = $this->lbFactory->getPrimaryDatabase();
161 $this->currentRevId = $dbw->newSelectQueryBuilder()
162 ->select( 'page_latest' )
163 ->from( 'page' )
164 ->where( [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ] )
165 ->caller( __METHOD__ )->fetchField();
166 }
167 return $this->currentRevId;
168 }
169
177 protected function emitEvents(
178 array $bitPars,
179 array $visibilityChangeMap,
180 array $tags,
181 LogEntry $logEntry,
182 bool $suppressed
183 ) {
184 // Figure out which bits got set, and which got unset.
185 $bitsSet = RevisionDeleter::extractBitfield( $bitPars, 0 );
186 $bitsUnset = RevisionRecord::SUPPRESSED_ALL &
187 ( ~ RevisionDeleter::extractBitfield( $bitPars, RevisionRecord::SUPPRESSED_ALL ) );
188
189 $page = $this->getPage();
190 $performer = $this->getUser();
191
192 // Hack: make sure we have a *proper* PageIdentity
193 if ( !$page instanceof ProperPageIdentity ) {
194 if ( !$page instanceof Title ) {
195 $page = Title::newFromPageIdentity( $page );
196 }
197
198 $page = $page->toPageIdentity();
199 }
200
201 $flags = [
203 ];
204
205 $this->eventDispatcher->dispatch(
207 $page,
208 $performer,
209 $this->getCurrent(),
210 $bitsSet,
211 $bitsUnset,
212 $visibilityChangeMap,
213 $logEntry->getComment(),
214 $tags,
215 $flags,
216 $logEntry->getTimestamp()
217 ),
218 $this->lbFactory
219 );
220 }
221
223 public function doPreCommitUpdates() {
224 Title::newFromPageIdentity( $this->page )->invalidateCache();
225 return Status::newGood();
226 }
227
229 public function doPostCommitUpdates( array $visibilityChangeMap ) {
230 $this->htmlCacheUpdater->purgeTitleUrls(
231 $this->page,
232 HTMLCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED
233 );
234 // Extensions that require referencing previous revisions may need this
235 $this->hookRunner->onArticleRevisionVisibilitySet(
236 Title::newFromPageIdentity( $this->page ),
237 $this->ids,
238 $visibilityChangeMap
239 );
240
241 return Status::newGood();
242 }
243}
244
246class_alias( RevDelRevisionList::class, 'RevDelRevisionList' );
Class to invalidate the CDN and HTMLFileCache entries associated with URLs/titles.
Formats change tags for display in HTML and use filter dropdown menus.
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Domain event representing a change to the visibility attributes of one of the page's revisions.
Item class for a archive table row by ar_rev_id – actually used via RevDelRevisionList.
emitEvents(array $bitPars, array $visibilityChangeMap, array $tags, LogEntry $logEntry, bool $suppressed)
static getRevdelConstant()
Get the revision deletion constant for this list type Override this function.1.22 int|null
newItem( $row)
Create an item object from a DB result row.RevisionItemBase
doPreCommitUpdates()
A hook for setVisibility(): do batch updates pre-commit.STUB Status
getType()
Get the internal type name of this list.Equal to the table name. Override this function....
__construct(IContextSource $context, PageIdentity $page, array $ids, private readonly LBFactory $lbFactory, HookContainer $hookContainer, private readonly HTMLCacheUpdater $htmlCacheUpdater, private readonly RevisionStore $revisionStore, private readonly DomainEventDispatcher $eventDispatcher, private readonly ChangeTagsFormatter $changeTagsFormatter,)
static suggestTarget( $target, array $ids)
Suggest a target for the revision deletion Optionally override this function.1.22 Title|null
static getRelationType()
Get the DB field name associated with the ID list.This used to populate the log_search table for find...
doPostCommitUpdates(array $visibilityChangeMap)
A hook for setVisibility(): do any necessary updates post-commit.STUB Status
static getRestriction()
Get the user right required for this list type Override this function.1.22 string|null
static extractBitfield(array $bitPars, $oldfield)
Put together a rev_deleted bitfield.
Page revision base class.
Service for looking up page revisions.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Represents a title within MediaWiki.
Definition Title.php:69
Overloads the relevant methods of the real ResultWrapper so it doesn't go anywhere near an actual dat...
Interface for objects which can provide a MediaWiki context on request.
Service for sending domain events to registered listeners.
An individual log entry.
Definition LogEntry.php:24
getTimestamp()
Get the timestamp when the action was executed.
getComment()
Get the user provided comment.
Interface for objects (potentially) representing an editable wiki page.
Interface for a page that is (or could be, or used to be) an editable wiki page.
Result wrapper for grabbing data queried from an IDatabase object.