86 if ( $this->page === false ) {
87 $this->page = $this->pageLookup->getExistingPageByText(
105 if ( $params[
'older_than'] !==
null && $params[
'newer_than'] !==
null ) {
107 new MessageValue(
'rest-pagehistory-incompatible-params' ), 400 );
110 if ( ( $params[
'older_than'] !==
null && $params[
'older_than'] < 1 ) ||
111 ( $params[
'newer_than'] !==
null && $params[
'newer_than'] < 1 )
114 new MessageValue(
'rest-pagehistory-param-range-error' ), 400 );
118 if ( $params[
'filter'] ===
'reverted' ) {
121 $tagIds[] = $this->changeTagDefStore->getId( $tagName );
128 $page = $this->getPage();
137 if ( !$this->
getAuthority()->authorizeRead(
'read', $page ) ) {
145 $relativeRevId = $params[
'older_than'] ?? $params[
'newer_than'] ?? 0;
146 if ( $relativeRevId ) {
148 $rev = $this->revisionStore->getRevisionByPageId(
160 $ts = $rev->getTimestamp();
161 if ( $ts ===
null ) {
173 $res = $this->getDbResults( $page, $params, $relativeRevId, $ts, $tagIds );
174 $response = $this->processDbResults(
$res, $page, $params );
188 $revQuery = $this->revisionStore->getQueryInfo();
190 'rev_page' => $page->
getId()
193 if ( $params[
'filter'] ) {
196 if ( isset(
$revQuery[
'tables'][
'temp_rev_user'] ) ) {
198 "temp_rev_user.revactor_rev = rev_id AND revactor_page = rev_page";
202 switch ( $params[
'filter'] ) {
204 $cond[] =
'EXISTS(' .
$dbr->selectSQLText(
208 'actor_rev_user.actor_user = ug_user',
209 'ug_group' => $this->groupPermissionsLookup->getGroupsWithPermission(
'bot' ),
210 'ug_expiry IS NULL OR ug_expiry >= ' .
$dbr->addQuotes(
$dbr->timestamp() )
214 $bitmask = $this->getBitmask();
216 $cond[] =
$dbr->bitAnd(
'rev_deleted', $bitmask ) .
" != $bitmask";
221 $cond[] =
"actor_user IS NULL";
222 $bitmask = $this->getBitmask();
224 $cond[] =
$dbr->bitAnd(
'rev_deleted', $bitmask ) .
" != $bitmask";
232 $cond[] =
'EXISTS(' .
$dbr->selectSQLText(
235 [
'ct_rev_id = rev_id',
'ct_tag_id' => $tagIds ],
241 $cond[] =
'rev_minor_edit != 0';
246 if ( $relativeRevId ) {
247 $op = $params[
'older_than'] ?
'<' :
'>';
248 $sort = $params[
'older_than'] ?
'DESC' :
'ASC';
249 $ts =
$dbr->addQuotes(
$dbr->timestamp( $ts ) );
250 $cond[] =
"rev_timestamp $op $ts OR " .
251 "(rev_timestamp = $ts AND rev_id $op $relativeRevId)";
252 $orderBy =
"rev_timestamp $sort, rev_id $sort";
254 $orderBy =
"rev_timestamp DESC, rev_id DESC";
258 $limit = self::REVISIONS_RETURN_LIMIT + 1;
266 'ORDER BY' => $orderBy,
283 if ( !$this->
getAuthority()->isAllowed(
'deletedhistory' ) ) {
284 $bitmask = RevisionRecord::DELETED_USER;
285 } elseif ( !$this->
getAuthority()->isAllowedAny(
'suppressrevision',
'viewsuppressed' ) ) {
286 $bitmask = RevisionRecord::DELETED_USER | RevisionRecord::DELETED_RESTRICTED;
304 foreach (
$res as $row ) {
305 $rev = $this->revisionStore->newRevisionFromRow(
307 IDBAccessObject::READ_NORMAL,
311 $firstRevId = $row->rev_id;
313 $lastRevId = $row->rev_id;
316 'id' => $rev->getId(),
317 'timestamp' =>
wfTimestamp( TS_ISO_8601, $rev->getTimestamp() ),
318 'minor' => $rev->isMinor(),
319 'size' => $rev->getSize()
324 $sizes[$rev->getId()] = $rev->getSize();
325 $parentId = $rev->getParentId();
327 $revision[
'parent_id'] = $parentId;
330 $comment = $rev->getComment( RevisionRecord::FOR_THIS_USER, $this->
getAuthority() );
331 $revision[
'comment'] = $comment ? $comment->text :
null;
333 $revUser = $rev->getUser( RevisionRecord::FOR_THIS_USER, $this->
getAuthority() );
335 $revision[
'user'] = [
336 'id' => $revUser->isRegistered() ? $revUser->getId() :
null,
337 'name' => $revUser->getName()
340 $revision[
'user'] =
null;
343 $revisions[] = $revision;
346 if ( count( $revisions ) == self::REVISIONS_RETURN_LIMIT ) {
353 foreach ( $revisions as $revision ) {
354 if ( isset( $revision[
'parent_id'] ) && !isset( $sizes[$revision[
'parent_id']] ) ) {
355 $unknownSizes[] = $revision[
'parent_id'];
358 if ( $unknownSizes ) {
359 $sizes += $this->revisionStore->getRevisionSizes( $unknownSizes );
361 foreach ( $revisions as &$revision ) {
362 $revision[
'delta'] =
null;
363 if ( isset( $revision[
'parent_id'] ) ) {
364 if ( isset( $sizes[$revision[
'parent_id']] ) ) {
365 $revision[
'delta'] = $revision[
'size'] - $sizes[$revision[
'parent_id']];
369 unset( $revision[
'parent_id'] );
373 if ( $revisions && $params[
'newer_than'] ) {
374 $revisions = array_reverse( $revisions );
376 $lastRevId = $firstRevId;
382 'revisions' => $revisions
388 if ( $params[
'newer_than'] ||
$res->numRows() > self::REVISIONS_RETURN_LIMIT ) {
391 if ( $params[
'older_than'] ||
392 ( $params[
'newer_than'] &&
$res->numRows() > self::REVISIONS_RETURN_LIMIT )
394 $newer = $firstRevId;
400 if ( isset( $params[
'filter'] ) ) {
401 $queryParts[
'filter'] = $params[
'filter'];
404 $pathParams = [
'title' => $this->titleFormatter->getPrefixedDBkey( $page ) ];
406 $response[
'latest'] = $this->
getRouteUrl( $pathParams, $queryParts );
408 if ( isset( $older ) ) {
410 $this->
getRouteUrl( $pathParams, $queryParts + [
'older_than' => $older ] );
412 if ( isset( $newer ) ) {
414 $this->
getRouteUrl( $pathParams, $queryParts + [
'newer_than' => $newer ] );
427 self::PARAM_SOURCE =>
'path',
428 ParamValidator::PARAM_TYPE =>
'string',
429 ParamValidator::PARAM_REQUIRED =>
true,
432 self::PARAM_SOURCE =>
'query',
433 ParamValidator::PARAM_TYPE =>
'integer',
434 ParamValidator::PARAM_REQUIRED =>
false,
437 self::PARAM_SOURCE =>
'query',
438 ParamValidator::PARAM_TYPE =>
'integer',
439 ParamValidator::PARAM_REQUIRED =>
false,
442 self::PARAM_SOURCE =>
'query',
443 ParamValidator::PARAM_TYPE => self::ALLOWED_FILTER_TYPES,
444 ParamValidator::PARAM_REQUIRED =>
false,
455 $page = $this->getPage();
460 return '"' . $page->getLatest() .
'"';
469 $page = $this->getPage();
474 $rev = $this->revisionStore->getKnownCurrentRevision( $page );
475 return $rev->getTimestamp();
482 return (
bool)$this->getPage();
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Handler class for Core REST API endpoints that perform operations on revisions.
getETag()
Returns an ETag representing a page's latest revision.
RevisionStore $revisionStore
const ALLOWED_FILTER_TYPES
ILoadBalancer $loadBalancer
getLastModified()
Returns the time of the last change to the page.
NameTableStore $changeTagDefStore
processDbResults( $res, $page, $params)
getBitmask()
Helper function for rev_deleted/user rights query conditions.
needsWriteAccess()
Indicates whether this route requires write access.
run( $title)
At most one of older_than and newer_than may be specified.
TitleFormatter $titleFormatter
getDbResults(ExistingPageRecord $page, array $params, $relativeRevId, $ts, $tagIds)
getParamSettings()
Fetch ParamValidator settings for parameters.
__construct(RevisionStore $revisionStore, NameTableStoreFactory $nameTableStoreFactory, GroupPermissionsLookup $groupPermissionsLookup, ILoadBalancer $loadBalancer, PageLookup $pageLookup, TitleFormatter $titleFormatter)
RevisionStore $revisionStore.
const REVISIONS_RETURN_LIMIT
ExistingPageRecord false null $page
GroupPermissionsLookup $groupPermissionsLookup
Interface for database access objects.
Service interface for looking up infermation about wiki pages.
getId( $wikiId=self::LOCAL)
Returns the page ID.