MediaWiki  master
RevDelRevisionList.php
Go to the documentation of this file.
1 <?php
33 
44 
46  private $lbFactory;
47 
49  private $hookRunner;
50 
52  private $htmlCacheUpdater;
53 
55  private $revisionStore;
56 
58  public $currentRevId;
59 
69  public function __construct(
70  IContextSource $context,
72  array $ids,
73  LBFactory $lbFactory,
74  HookContainer $hookContainer,
75  HtmlCacheUpdater $htmlCacheUpdater,
76  RevisionStore $revisionStore
77  ) {
78  parent::__construct( $context, $page, $ids, $lbFactory );
79  $this->lbFactory = $lbFactory;
80  $this->hookRunner = new HookRunner( $hookContainer );
81  $this->htmlCacheUpdater = $htmlCacheUpdater;
82  $this->revisionStore = $revisionStore;
83  }
84 
85  public function getType() {
86  return 'revision';
87  }
88 
89  public static function getRelationType() {
90  return 'rev_id';
91  }
92 
93  public static function getRestriction() {
94  return 'deleterevision';
95  }
96 
97  public static function getRevdelConstant() {
98  return RevisionRecord::DELETED_TEXT;
99  }
100 
101  public static function suggestTarget( $target, array $ids ) {
102  $revisionRecord = MediaWikiServices::getInstance()
103  ->getRevisionLookup()
104  ->getRevisionById( $ids[0] );
105 
106  if ( $revisionRecord ) {
107  return Title::newFromLinkTarget( $revisionRecord->getPageAsLinkTarget() );
108  }
109  return $target;
110  }
111 
116  public function doQuery( $db ) {
117  $ids = array_map( 'intval', $this->ids );
118  $revQuery = $this->revisionStore->getQueryInfo( [ 'page', 'user' ] );
119  $queryInfo = [
120  'tables' => $revQuery['tables'],
121  'fields' => $revQuery['fields'],
122  'conds' => [
123  'rev_page' => $this->page->getId(),
124  'rev_id' => $ids,
125  ],
126  'options' => [
127  'ORDER BY' => 'rev_id DESC',
128  'USE INDEX' => [ 'revision' => 'PRIMARY' ] // workaround for MySQL bug (T104313)
129  ],
130  'join_conds' => $revQuery['joins'],
131  ];
133  $queryInfo['tables'],
134  $queryInfo['fields'],
135  $queryInfo['conds'],
136  $queryInfo['join_conds'],
137  $queryInfo['options'],
138  ''
139  );
140 
141  $live = $db->select(
142  $queryInfo['tables'],
143  $queryInfo['fields'],
144  $queryInfo['conds'],
145  __METHOD__,
146  $queryInfo['options'],
147  $queryInfo['join_conds']
148  );
149  if ( $live->numRows() >= count( $ids ) ) {
150  // All requested revisions are live, keeps things simple!
151  return $live;
152  }
153 
154  $arQuery = $this->revisionStore->getArchiveQueryInfo();
155  $archiveQueryInfo = [
156  'tables' => $arQuery['tables'],
157  'fields' => $arQuery['fields'],
158  'conds' => [
159  'ar_rev_id' => $ids,
160  ],
161  'options' => [ 'ORDER BY' => 'ar_rev_id DESC' ],
162  'join_conds' => $arQuery['joins'],
163  ];
164 
166  $archiveQueryInfo['tables'],
167  $archiveQueryInfo['fields'],
168  $archiveQueryInfo['conds'],
169  $archiveQueryInfo['join_conds'],
170  $archiveQueryInfo['options'],
171  ''
172  );
173 
174  // Check if any requested revisions are available fully deleted.
175  $archived = $db->select(
176  $archiveQueryInfo['tables'],
177  $archiveQueryInfo['fields'],
178  $archiveQueryInfo['conds'],
179  __METHOD__,
180  $archiveQueryInfo['options'],
181  $archiveQueryInfo['join_conds']
182  );
183 
184  if ( $archived->numRows() == 0 ) {
185  return $live;
186  } elseif ( $live->numRows() == 0 ) {
187  return $archived;
188  } else {
189  // Combine the two! Whee
190  $rows = [];
191  foreach ( $live as $row ) {
192  $rows[$row->rev_id] = $row;
193  }
194  foreach ( $archived as $row ) {
195  $rows[$row->ar_rev_id] = $row;
196  }
197  krsort( $rows );
198  return new FakeResultWrapper( array_values( $rows ) );
199  }
200  }
201 
202  public function newItem( $row ) {
203  if ( isset( $row->rev_id ) ) {
204  return new RevDelRevisionItem( $this, $row );
205  } elseif ( isset( $row->ar_rev_id ) ) {
206  return new RevDelArchivedRevisionItem( $this, $row );
207  } else {
208  // This shouldn't happen. :)
209  throw new InvalidArgumentException( 'Invalid row type in RevDelRevisionList' );
210  }
211  }
212 
213  public function getCurrent() {
214  if ( $this->currentRevId === null ) {
215  $dbw = $this->lbFactory->getPrimaryDatabase();
216  $this->currentRevId = $dbw->selectField(
217  'page',
218  'page_latest',
219  [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ],
220  __METHOD__
221  );
222  }
223  return $this->currentRevId;
224  }
225 
226  public function getSuppressBit() {
227  return RevisionRecord::DELETED_RESTRICTED;
228  }
229 
230  public function doPreCommitUpdates() {
231  Title::castFromPageIdentity( $this->page )->invalidateCache();
232  return Status::newGood();
233  }
234 
235  public function doPostCommitUpdates( array $visibilityChangeMap ) {
236  $this->htmlCacheUpdater->purgeTitleUrls(
237  $this->page,
238  HtmlCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED
239  );
240  // Extensions that require referencing previous revisions may need this
241  $this->hookRunner->onArticleRevisionVisibilitySet(
242  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable castFrom does not return null here
243  Title::castFromPageIdentity( $this->page ),
244  $this->ids,
245  $visibilityChangeMap
246  );
247 
248  return Status::newGood();
249  }
250 }
static modifyDisplayQuery(&$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag='', bool $exclude=false)
Applies all tags-related changes to a query.
Definition: ChangeTags.php:904
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...
Definition: HookRunner.php:568
Service locator for MediaWiki core services.
Page revision base class.
Service for looking up page revisions.
Represents a title within MediaWiki.
Definition: Title.php:82
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.
__construct(IContextSource $context, PageIdentity $page, array $ids, LBFactory $lbFactory, HookContainer $hookContainer, HtmlCacheUpdater $htmlCacheUpdater, RevisionStore $revisionStore)
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.
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.
PageIdentity $page
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:85
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.
Interface for objects (potentially) representing an editable wiki page.
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:36
Result wrapper for grabbing data queried from an IDatabase object.
$revQuery