MediaWiki  master
RevDelRevisionList.php
Go to the documentation of this file.
1 <?php
31 
42 
44  private $lbFactory;
45 
47  private $hookRunner;
48 
51 
53  private $revisionStore;
54 
56  private $wanObjectCache;
57 
59  public $currentRevId;
60 
71  public function __construct(
74  array $ids,
76  HookContainer $hookContainer,
80  ) {
81  parent::__construct( $context, $page, $ids, $lbFactory );
82  $this->lbFactory = $lbFactory;
83  $this->hookRunner = new HookRunner( $hookContainer );
84  $this->htmlCacheUpdater = $htmlCacheUpdater;
85  $this->revisionStore = $revisionStore;
86  $this->wanObjectCache = $wanObjectCache;
87  }
88 
89  public function getType() {
90  return 'revision';
91  }
92 
93  public static function getRelationType() {
94  return 'rev_id';
95  }
96 
97  public static function getRestriction() {
98  return 'deleterevision';
99  }
100 
101  public static function getRevdelConstant() {
102  return RevisionRecord::DELETED_TEXT;
103  }
104 
105  public static function suggestTarget( $target, array $ids ) {
106  $revisionRecord = MediaWikiServices::getInstance()
107  ->getRevisionLookup()
108  ->getRevisionById( $ids[0] );
109 
110  if ( $revisionRecord ) {
111  return Title::newFromLinkTarget( $revisionRecord->getPageAsLinkTarget() );
112  }
113  return $target;
114  }
115 
120  public function doQuery( $db ) {
121  $ids = array_map( 'intval', $this->ids );
122  $revQuery = $this->revisionStore->getQueryInfo( [ 'page', 'user' ] );
123  $queryInfo = [
124  'tables' => $revQuery['tables'],
125  'fields' => $revQuery['fields'],
126  'conds' => [
127  'rev_page' => $this->page->getId(),
128  'rev_id' => $ids,
129  ],
130  'options' => [
131  'ORDER BY' => 'rev_id DESC',
132  'USE INDEX' => [ 'revision' => 'PRIMARY' ] // workaround for MySQL bug (T104313)
133  ],
134  'join_conds' => $revQuery['joins'],
135  ];
137  $queryInfo['tables'],
138  $queryInfo['fields'],
139  $queryInfo['conds'],
140  $queryInfo['join_conds'],
141  $queryInfo['options'],
142  ''
143  );
144 
145  $live = $db->select(
146  $queryInfo['tables'],
147  $queryInfo['fields'],
148  $queryInfo['conds'],
149  __METHOD__,
150  $queryInfo['options'],
151  $queryInfo['join_conds']
152  );
153  if ( $live->numRows() >= count( $ids ) ) {
154  // All requested revisions are live, keeps things simple!
155  return $live;
156  }
157 
158  $arQuery = $this->revisionStore->getArchiveQueryInfo();
159  $archiveQueryInfo = [
160  'tables' => $arQuery['tables'],
161  'fields' => $arQuery['fields'],
162  'conds' => [
163  'ar_rev_id' => $ids,
164  ],
165  'options' => [ 'ORDER BY' => 'ar_rev_id DESC' ],
166  'join_conds' => $arQuery['joins'],
167  ];
168 
170  $archiveQueryInfo['tables'],
171  $archiveQueryInfo['fields'],
172  $archiveQueryInfo['conds'],
173  $archiveQueryInfo['join_conds'],
174  $archiveQueryInfo['options'],
175  ''
176  );
177 
178  // Check if any requested revisions are available fully deleted.
179  $archived = $db->select(
180  $archiveQueryInfo['tables'],
181  $archiveQueryInfo['fields'],
182  $archiveQueryInfo['conds'],
183  __METHOD__,
184  $archiveQueryInfo['options'],
185  $archiveQueryInfo['join_conds']
186  );
187 
188  if ( $archived->numRows() == 0 ) {
189  return $live;
190  } elseif ( $live->numRows() == 0 ) {
191  return $archived;
192  } else {
193  // Combine the two! Whee
194  $rows = [];
195  foreach ( $live as $row ) {
196  $rows[$row->rev_id] = $row;
197  }
198  foreach ( $archived as $row ) {
199  $rows[$row->ar_rev_id] = $row;
200  }
201  krsort( $rows );
202  return new FakeResultWrapper( array_values( $rows ) );
203  }
204  }
205 
206  public function newItem( $row ) {
207  if ( isset( $row->rev_id ) ) {
208  return new RevDelRevisionItem( $this, $row );
209  } elseif ( isset( $row->ar_rev_id ) ) {
210  return new RevDelArchivedRevisionItem( $this, $row );
211  } else {
212  // This shouldn't happen. :)
213  throw new MWException( 'Invalid row type in RevDelRevisionList' );
214  }
215  }
216 
217  public function getCurrent() {
218  if ( $this->currentRevId === null ) {
219  $dbw = $this->lbFactory->getMainLB()->getConnectionRef( DB_PRIMARY );
220  $this->currentRevId = $dbw->selectField(
221  'page',
222  'page_latest',
223  [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ],
224  __METHOD__
225  );
226  }
227  return $this->currentRevId;
228  }
229 
230  public function getSuppressBit() {
231  return RevisionRecord::DELETED_RESTRICTED;
232  }
233 
234  public function doPreCommitUpdates() {
235  Title::castFromPageIdentity( $this->page )->invalidateCache();
236  return Status::newGood();
237  }
238 
239  public function doPostCommitUpdates( array $visibilityChangeMap ) {
240  $this->htmlCacheUpdater->purgeTitleUrls(
241  $this->page,
242  HtmlCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED
243  );
244  // Extensions that require referencing previous revisions may need this
245  $this->hookRunner->onArticleRevisionVisibilitySet(
246  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable castFrom does not return null here
247  Title::castFromPageIdentity( $this->page ),
248  $this->ids,
249  $visibilityChangeMap
250  );
251  $this->wanObjectCache->touchCheckKey(
252  "RevDelRevisionList:page:{$this->page->getID()}}"
253  );
254 
255  return Status::newGood();
256  }
257 }
static modifyDisplayQuery(&$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag='', bool $exclude=false)
Applies all tags-related changes to a query.
Definition: ChangeTags.php:896
IContextSource $context
Class to invalidate the CDN and HTMLFileCache entries associated with URLs/titles.
MediaWiki exception.
Definition: MWException.php:29
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:562
Service locator for MediaWiki core services.
Page revision base class.
Service for looking up page revisions.
Item class for a archive table row by ar_rev_id – actually used via RevDelRevisionList.
List for revision table items.
getSuppressBit()
Get the integer value of the flag used for suppression.
doPostCommitUpdates(array $visibilityChangeMap)
A hook for setVisibility(): do any necessary updates post-commit.
static getRevdelConstant()
Get the revision deletion constant for this list type Override this function.
static getRelationType()
Get the DB field name associated with the ID list.
WANObjectCache $wanObjectCache
HtmlCacheUpdater $htmlCacheUpdater
static suggestTarget( $target, array $ids)
Suggest a target for the revision deletion Optionally override this function.
static getRestriction()
Get the user right required for this list type Override this function.
doPreCommitUpdates()
A hook for setVisibility(): do batch updates pre-commit.
getType()
Get the internal type name of this list.
newItem( $row)
Create an item object from a DB result row.
RevisionStore $revisionStore
__construct(IContextSource $context, PageIdentity $page, array $ids, LBFactory $lbFactory, HookContainer $hookContainer, HtmlCacheUpdater $htmlCacheUpdater, RevisionStore $revisionStore, WANObjectCache $wanObjectCache)
PageIdentity $page
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:82
static newFromLinkTarget(LinkTarget $linkTarget, $forceClone='')
Returns a Title given a LinkTarget.
Definition: Title.php:282
static castFromPageIdentity(?PageIdentity $pageIdentity)
Return a Title for a given PageIdentity.
Definition: Title.php:319
Multi-datacenter aware caching interface.
Overloads the relevant methods of the real ResultWrapper so it doesn't go anywhere near an actual dat...
An interface for generating database load balancers.
Definition: LBFactory.php:43
Interface for objects which can provide a MediaWiki context on request.
Interface for objects (potentially) representing an editable wiki page.
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:39
const DB_PRIMARY
Definition: defines.php:28
$revQuery