MediaWiki master
RevDelRevisionList.php
Go to the documentation of this file.
1<?php
9
10use InvalidArgumentException;
11use LogEntry;
28
39
41 private $lbFactory;
42
44 private $hookRunner;
45
47 private $htmlCacheUpdater;
48
50 private $revisionStore;
51
54 private DomainEventDispatcher $eventDispatcher;
55
56 public function __construct(
57 IContextSource $context,
59 array $ids,
60 LBFactory $lbFactory,
61 HookContainer $hookContainer,
62 HTMLCacheUpdater $htmlCacheUpdater,
63 RevisionStore $revisionStore,
64 DomainEventDispatcher $eventDispatcher
65 ) {
66 parent::__construct( $context, $page, $ids, $lbFactory );
67 $this->lbFactory = $lbFactory;
68 $this->hookRunner = new HookRunner( $hookContainer );
69 $this->htmlCacheUpdater = $htmlCacheUpdater;
70 $this->revisionStore = $revisionStore;
71 $this->eventDispatcher = $eventDispatcher;
72 }
73
75 public function getType() {
76 return 'revision';
77 }
78
80 public static function getRelationType() {
81 return 'rev_id';
82 }
83
85 public static function getRestriction() {
86 return 'deleterevision';
87 }
88
90 public static function getRevdelConstant() {
91 return RevisionRecord::DELETED_TEXT;
92 }
93
95 public static function suggestTarget( $target, array $ids ) {
96 $revisionRecord = MediaWikiServices::getInstance()
97 ->getRevisionLookup()
98 ->getRevisionById( $ids[0] );
99
100 if ( $revisionRecord ) {
101 return Title::newFromPageIdentity( $revisionRecord->getPage() );
102 }
103 return $target;
104 }
105
110 public function doQuery( $db ) {
111 $ids = array_map( 'intval', $this->ids );
112 $queryBuilder = $this->revisionStore->newSelectQueryBuilder( $db )
113 ->joinComment()
114 ->joinUser()
115 ->joinPage()
116 ->where( [ 'rev_page' => $this->page->getId(), 'rev_id' => $ids ] )
117 ->orderBy( 'rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC )
118 // workaround for MySQL bug (T104313)
119 ->useIndex( [ 'revision' => 'PRIMARY' ] );
120
121 MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'revision' );
122
123 $live = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
124 if ( $live->numRows() >= count( $ids ) ) {
125 // All requested revisions are live, keeps things simple!
126 return $live;
127 }
128
129 $queryBuilder = $this->revisionStore->newArchiveSelectQueryBuilder( $db )
130 ->joinComment()
131 ->where( [ 'ar_rev_id' => $ids ] )
132 ->orderBy( 'ar_rev_id', \Wikimedia\Rdbms\SelectQueryBuilder::SORT_DESC );
133
134 MediaWikiServices::getInstance()->getChangeTagsStore()->modifyDisplayQueryBuilder( $queryBuilder, 'archive' );
135
136 // Check if any requested revisions are available fully deleted.
137 $archived = $queryBuilder->caller( __METHOD__ )->fetchResultSet();
138
139 if ( $archived->numRows() == 0 ) {
140 return $live;
141 } elseif ( $live->numRows() == 0 ) {
142 return $archived;
143 } else {
144 // Combine the two! Whee
145 $rows = [];
146 foreach ( $live as $row ) {
147 $rows[$row->rev_id] = $row;
148 }
149 foreach ( $archived as $row ) {
150 $rows[$row->ar_rev_id] = $row;
151 }
152 krsort( $rows );
153 return new FakeResultWrapper( array_values( $rows ) );
154 }
155 }
156
158 public function newItem( $row ) {
159 if ( isset( $row->rev_id ) ) {
160 return new RevDelRevisionItem( $this, $row );
161 } elseif ( isset( $row->ar_rev_id ) ) {
162 return new RevDelArchivedRevisionItem( $this, $row, $this->lbFactory );
163 } else {
164 // This shouldn't happen. :)
165 throw new InvalidArgumentException( 'Invalid row type in RevDelRevisionList' );
166 }
167 }
168
170 public function getCurrent() {
171 if ( $this->currentRevId === null ) {
172 $dbw = $this->lbFactory->getPrimaryDatabase();
173 $this->currentRevId = $dbw->newSelectQueryBuilder()
174 ->select( 'page_latest' )
175 ->from( 'page' )
176 ->where( [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ] )
177 ->caller( __METHOD__ )->fetchField();
178 }
179 return $this->currentRevId;
180 }
181
189 protected function emitEvents(
190 array $bitPars,
191 array $visibilityChangeMap,
192 array $tags,
193 LogEntry $logEntry,
194 bool $suppressed
195 ) {
196 // Figure out which bits got set, and which got unset.
197 $bitsSet = RevisionDeleter::extractBitfield( $bitPars, 0 );
198 $bitsUnset = RevisionRecord::SUPPRESSED_ALL &
199 ( ~ RevisionDeleter::extractBitfield( $bitPars, RevisionRecord::SUPPRESSED_ALL ) );
200
201 $page = $this->getPage();
202 $performer = $this->getUser();
203
204 // Hack: make sure we have a *proper* PageIdentity
205 if ( !$page instanceof ProperPageIdentity ) {
206 if ( !$page instanceof Title ) {
207 $page = Title::newFromPageIdentity( $page );
208 }
209
210 $page = $page->toPageIdentity();
211 }
212
213 $flags = [
215 ];
216
217 $this->eventDispatcher->dispatch(
219 $page,
220 $performer,
221 $this->getCurrent(),
222 $bitsSet,
223 $bitsUnset,
224 $visibilityChangeMap,
225 $logEntry->getComment(),
226 $tags,
227 $flags,
228 $logEntry->getTimestamp()
229 ),
230 $this->lbFactory
231 );
232 }
233
235 public function doPreCommitUpdates() {
236 Title::newFromPageIdentity( $this->page )->invalidateCache();
237 return Status::newGood();
238 }
239
241 public function doPostCommitUpdates( array $visibilityChangeMap ) {
242 $this->htmlCacheUpdater->purgeTitleUrls(
243 $this->page,
244 HTMLCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED
245 );
246 // Extensions that require referencing previous revisions may need this
247 $this->hookRunner->onArticleRevisionVisibilitySet(
248 Title::newFromPageIdentity( $this->page ),
249 $this->ids,
250 $visibilityChangeMap
251 );
252
253 return Status::newGood();
254 }
255}
256
258class_alias( RevDelRevisionList::class, 'RevDelRevisionList' );
Class to invalidate the CDN and HTMLFileCache entries associated with URLs/titles.
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, LBFactory $lbFactory, HookContainer $hookContainer, HTMLCacheUpdater $htmlCacheUpdater, RevisionStore $revisionStore, DomainEventDispatcher $eventDispatcher)
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.
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.