MediaWiki  master
ArchivedRevisionLookup.php
Go to the documentation of this file.
1 <?php
22 
23 use ChangeTags;
27 
32 
34  private $loadBalancer;
35 
37  private $revisionStore;
38 
43  public function __construct(
46  ) {
47  $this->loadBalancer = $loadBalancer;
48  $this->revisionStore = $revisionStore;
49  }
50 
58  public function listRevisions( PageIdentity $page ) {
59  $queryInfo = $this->revisionStore->getArchiveQueryInfo();
60 
61  $conds = [
62  'ar_namespace' => $page->getNamespace(),
63  'ar_title' => $page->getDBkey(),
64  ];
65 
66  // NOTE: ordering by ar_timestamp and ar_id, to remove ambiguity.
67  // XXX: Ideally, we would be ordering by ar_timestamp and ar_rev_id, but since we
68  // don't have an index on ar_rev_id, that causes a file sort.
69  $options = [ 'ORDER BY' => [ 'ar_timestamp DESC', 'ar_id DESC' ] ];
70 
72  $queryInfo['tables'],
73  $queryInfo['fields'],
74  $conds,
75  $queryInfo['joins'],
76  $options,
77  ''
78  );
79 
80  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
81  return $dbr->select(
82  $queryInfo['tables'],
83  $queryInfo['fields'],
84  $conds,
85  __METHOD__,
86  $options,
87  $queryInfo['joins']
88  );
89  }
90 
100  public function getRevisionRecordByTimestamp( PageIdentity $page, $timestamp ): ?RevisionRecord {
101  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
102  return $this->getRevisionByConditions(
103  $page,
104  [ 'ar_timestamp' => $dbr->timestamp( $timestamp ) ]
105  );
106  }
107 
115  public function getArchivedRevisionRecord( PageIdentity $page, int $revId ): ?RevisionRecord {
116  return $this->getRevisionByConditions( $page, [ 'ar_rev_id' => $revId ] );
117  }
118 
126  private function getRevisionByConditions(
127  PageIdentity $page,
128  array $conditions,
129  array $options = []
130  ): ?RevisionRecord {
131  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
132  $arQuery = $this->revisionStore->getArchiveQueryInfo();
133 
134  $conditions += [
135  'ar_namespace' => $page->getNamespace(),
136  'ar_title' => $page->getDBkey(),
137  ];
138 
139  $row = $dbr->selectRow(
140  $arQuery['tables'],
141  $arQuery['fields'],
142  $conditions,
143  __METHOD__,
144  $options,
145  $arQuery['joins']
146  );
147 
148  if ( $row ) {
149  return $this->revisionStore->newRevisionFromArchiveRow( $row, 0, $page );
150  }
151 
152  return null;
153  }
154 
166  public function getPreviousRevisionRecord( PageIdentity $page, string $timestamp ): ?RevisionRecord {
167  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
168 
169  // Check the previous deleted revision...
170  $row = $dbr->selectRow( 'archive',
171  [ 'ar_rev_id', 'ar_timestamp' ],
172  [ 'ar_namespace' => $page->getNamespace(),
173  'ar_title' => $page->getDBkey(),
174  'ar_timestamp < ' .
175  $dbr->addQuotes( $dbr->timestamp( $timestamp ) ) ],
176  __METHOD__,
177  [
178  'ORDER BY' => 'ar_timestamp DESC',
179  ] );
180  $prevDeleted = $row ? wfTimestamp( TS_MW, $row->ar_timestamp ) : false;
181  $prevDeletedId = $row ? intval( $row->ar_rev_id ) : null;
182 
183  $row = $dbr->selectRow( [ 'page', 'revision' ],
184  [ 'rev_id', 'rev_timestamp' ],
185  [
186  'page_namespace' => $page->getNamespace(),
187  'page_title' => $page->getDBkey(),
188  'page_id = rev_page',
189  'rev_timestamp < ' .
190  $dbr->addQuotes( $dbr->timestamp( $timestamp ) ) ],
191  __METHOD__,
192  [
193  'ORDER BY' => 'rev_timestamp DESC',
194  ] );
195  $prevLive = $row ? wfTimestamp( TS_MW, $row->rev_timestamp ) : false;
196  $prevLiveId = $row ? intval( $row->rev_id ) : null;
197 
198  if ( $prevLive && $prevLive > $prevDeleted ) {
199  // Most prior revision was live
200  $rec = $this->revisionStore->getRevisionById( $prevLiveId );
201  } elseif ( $prevDeleted ) {
202  // Most prior revision was deleted
203  $rec = $this->getArchivedRevisionRecord( $page, $prevDeletedId );
204  } else {
205  $rec = null;
206  }
207 
208  return $rec;
209  }
210 
218  public function getLastRevisionId( PageIdentity $page ) {
219  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
220  $revId = $dbr->selectField(
221  'archive',
222  'ar_rev_id',
223  [ 'ar_namespace' => $page->getNamespace(),
224  'ar_title' => $page->getDBkey() ],
225  __METHOD__,
226  [ 'ORDER BY' => [ 'ar_timestamp DESC', 'ar_id DESC' ] ]
227  );
228 
229  return $revId ? intval( $revId ) : false;
230  }
231 
240  public function hasArchivedRevisions( PageIdentity $page ): bool {
241  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
242  $row = $dbr->selectRow(
243  'archive',
244  '1', // We don't care about the value. Allow the database to optimize.
245  [ 'ar_namespace' => $page->getNamespace(),
246  'ar_title' => $page->getDBkey() ],
247  __METHOD__
248  );
249 
250  return (bool)$row;
251  }
252 
253 }
Page\PageIdentity
Interface for objects (potentially) representing an editable wiki page.
Definition: PageIdentity.php:64
MediaWiki\Revision\ArchivedRevisionLookup\getPreviousRevisionRecord
getPreviousRevisionRecord(PageIdentity $page, string $timestamp)
Return the most-previous revision, either live or deleted, against the deleted revision given by time...
Definition: ArchivedRevisionLookup.php:166
MediaWiki\Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:47
MediaWiki\Revision\ArchivedRevisionLookup\$loadBalancer
ILoadBalancer $loadBalancer
Definition: ArchivedRevisionLookup.php:34
MediaWiki\Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:88
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1665
MediaWiki\Revision\ArchivedRevisionLookup\hasArchivedRevisions
hasArchivedRevisions(PageIdentity $page)
Quick check if any archived revisions are present for the page.
Definition: ArchivedRevisionLookup.php:240
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\Revision
Definition: ArchivedRevisionLookup.php:21
MediaWiki\Revision\ArchivedRevisionLookup\getRevisionRecordByTimestamp
getRevisionRecordByTimestamp(PageIdentity $page, $timestamp)
Return a RevisionRecord object containing data for the deleted revision.
Definition: ArchivedRevisionLookup.php:100
ChangeTags\modifyDisplayQuery
static modifyDisplayQuery(&$tables, &$fields, &$conds, &$join_conds, &$options, $filter_tag='')
Applies all tags-related changes to a query.
Definition: ChangeTags.php:891
MediaWiki\Revision\ArchivedRevisionLookup\getArchivedRevisionRecord
getArchivedRevisionRecord(PageIdentity $page, int $revId)
Return the archived revision with the given ID.
Definition: ArchivedRevisionLookup.php:115
Wikimedia\Rdbms\IResultWrapper
Result wrapper for grabbing data queried from an IDatabase object.
Definition: IResultWrapper.php:26
Page\PageReference\getNamespace
getNamespace()
Returns the page's namespace number.
ChangeTags
Definition: ChangeTags.php:32
MediaWiki\Revision\ArchivedRevisionLookup\getLastRevisionId
getLastRevisionId(PageIdentity $page)
Returns the ID of the latest deleted revision.
Definition: ArchivedRevisionLookup.php:218
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
MediaWiki\Revision\ArchivedRevisionLookup\__construct
__construct(ILoadBalancer $loadBalancer, RevisionStore $revisionStore)
Definition: ArchivedRevisionLookup.php:43
Page\PageReference\getDBkey
getDBkey()
Get the page title in DB key form.
MediaWiki\Revision\ArchivedRevisionLookup\getRevisionByConditions
getRevisionByConditions(PageIdentity $page, array $conditions, array $options=[])
Definition: ArchivedRevisionLookup.php:126
MediaWiki\Revision\ArchivedRevisionLookup
Definition: ArchivedRevisionLookup.php:31
MediaWiki\Revision\ArchivedRevisionLookup\listRevisions
listRevisions(PageIdentity $page)
List the revisions of the given page.
Definition: ArchivedRevisionLookup.php:58
MediaWiki\Revision\ArchivedRevisionLookup\$revisionStore
RevisionStore $revisionStore
Definition: ArchivedRevisionLookup.php:37
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81