MediaWiki  master
RevDelRevisionList.php
Go to the documentation of this file.
1 <?php
34 
45 
47  private $lbFactory;
48 
50  private $hookRunner;
51 
53  private $htmlCacheUpdater;
54 
56  private $revisionStore;
57 
59  public $currentRevId;
60 
70  public function __construct(
71  IContextSource $context,
73  array $ids,
74  LBFactory $lbFactory,
75  HookContainer $hookContainer,
76  HtmlCacheUpdater $htmlCacheUpdater,
77  RevisionStore $revisionStore
78  ) {
79  parent::__construct( $context, $page, $ids, $lbFactory );
80  $this->lbFactory = $lbFactory;
81  $this->hookRunner = new HookRunner( $hookContainer );
82  $this->htmlCacheUpdater = $htmlCacheUpdater;
83  $this->revisionStore = $revisionStore;
84  }
85 
86  public function getType() {
87  return 'revision';
88  }
89 
90  public static function getRelationType() {
91  return 'rev_id';
92  }
93 
94  public static function getRestriction() {
95  return 'deleterevision';
96  }
97 
98  public static function getRevdelConstant() {
99  return RevisionRecord::DELETED_TEXT;
100  }
101 
102  public static function suggestTarget( $target, array $ids ) {
103  $revisionRecord = MediaWikiServices::getInstance()
104  ->getRevisionLookup()
105  ->getRevisionById( $ids[0] );
106 
107  if ( $revisionRecord ) {
108  return Title::newFromLinkTarget( $revisionRecord->getPageAsLinkTarget() );
109  }
110  return $target;
111  }
112 
117  public function doQuery( $db ) {
118  $ids = array_map( 'intval', $this->ids );
119  $revQuery = $this->revisionStore->getQueryInfo( [ 'page', 'user' ] );
120  $queryInfo = [
121  'tables' => $revQuery['tables'],
122  'fields' => $revQuery['fields'],
123  'conds' => [
124  'rev_page' => $this->page->getId(),
125  'rev_id' => $ids,
126  ],
127  'options' => [
128  'ORDER BY' => 'rev_id DESC',
129  'USE INDEX' => [ 'revision' => 'PRIMARY' ] // workaround for MySQL bug (T104313)
130  ],
131  'join_conds' => $revQuery['joins'],
132  ];
134  $queryInfo['tables'],
135  $queryInfo['fields'],
136  $queryInfo['conds'],
137  $queryInfo['join_conds'],
138  $queryInfo['options'],
139  ''
140  );
141 
142  $live = $db->select(
143  $queryInfo['tables'],
144  $queryInfo['fields'],
145  $queryInfo['conds'],
146  __METHOD__,
147  $queryInfo['options'],
148  $queryInfo['join_conds']
149  );
150  if ( $live->numRows() >= count( $ids ) ) {
151  // All requested revisions are live, keeps things simple!
152  return $live;
153  }
154 
155  $arQuery = $this->revisionStore->getArchiveQueryInfo();
156  $archiveQueryInfo = [
157  'tables' => $arQuery['tables'],
158  'fields' => $arQuery['fields'],
159  'conds' => [
160  'ar_rev_id' => $ids,
161  ],
162  'options' => [ 'ORDER BY' => 'ar_rev_id DESC' ],
163  'join_conds' => $arQuery['joins'],
164  ];
165 
167  $archiveQueryInfo['tables'],
168  $archiveQueryInfo['fields'],
169  $archiveQueryInfo['conds'],
170  $archiveQueryInfo['join_conds'],
171  $archiveQueryInfo['options'],
172  ''
173  );
174 
175  // Check if any requested revisions are available fully deleted.
176  $archived = $db->select(
177  $archiveQueryInfo['tables'],
178  $archiveQueryInfo['fields'],
179  $archiveQueryInfo['conds'],
180  __METHOD__,
181  $archiveQueryInfo['options'],
182  $archiveQueryInfo['join_conds']
183  );
184 
185  if ( $archived->numRows() == 0 ) {
186  return $live;
187  } elseif ( $live->numRows() == 0 ) {
188  return $archived;
189  } else {
190  // Combine the two! Whee
191  $rows = [];
192  foreach ( $live as $row ) {
193  $rows[$row->rev_id] = $row;
194  }
195  foreach ( $archived as $row ) {
196  $rows[$row->ar_rev_id] = $row;
197  }
198  krsort( $rows );
199  return new FakeResultWrapper( array_values( $rows ) );
200  }
201  }
202 
203  public function newItem( $row ) {
204  if ( isset( $row->rev_id ) ) {
205  return new RevDelRevisionItem( $this, $row );
206  } elseif ( isset( $row->ar_rev_id ) ) {
207  return new RevDelArchivedRevisionItem( $this, $row );
208  } else {
209  // This shouldn't happen. :)
210  throw new InvalidArgumentException( 'Invalid row type in RevDelRevisionList' );
211  }
212  }
213 
214  public function getCurrent() {
215  if ( $this->currentRevId === null ) {
216  $dbw = $this->lbFactory->getPrimaryDatabase();
217  $this->currentRevId = $dbw->newSelectQueryBuilder()
218  ->select( 'page_latest' )
219  ->from( 'page' )
220  ->where( [ 'page_namespace' => $this->page->getNamespace(), 'page_title' => $this->page->getDBkey() ] )
221  ->caller( __METHOD__ )->fetchField();
222  }
223  return $this->currentRevId;
224  }
225 
226  public function doPreCommitUpdates() {
227  Title::newFromPageIdentity( $this->page )->invalidateCache();
228  return Status::newGood();
229  }
230 
231  public function doPostCommitUpdates( array $visibilityChangeMap ) {
232  $this->htmlCacheUpdater->purgeTitleUrls(
233  $this->page,
234  HtmlCacheUpdater::PURGE_INTENT_TXROUND_REFLECTED
235  );
236  // Extensions that require referencing previous revisions may need this
237  $this->hookRunner->onArticleRevisionVisibilitySet(
238  Title::newFromPageIdentity( $this->page ),
239  $this->ids,
240  $visibilityChangeMap
241  );
242 
243  return Status::newGood();
244  }
245 }
static modifyDisplayQuery(&$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag='', bool $exclude=false)
Applies all tags-related changes to a query.
Definition: ChangeTags.php:631
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.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:58
Represents a title within MediaWiki.
Definition: Title.php:76
Item class for a archive table row by ar_rev_id – actually used via RevDelRevisionList.
List for revision table items.
__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
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.