MediaWiki  master
PageHistoryCountHandler.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\Rest\Handler;
4 
14 use RequestContext;
15 use Title;
16 use User;
17 use WANObjectCache;
23 
29  private const COUNT_LIMITS = [
30  'anonymous' => 10000,
31  'bot' => 10000,
32  'editors' => 25000,
33  'edits' => 30000,
34  'minor' => 1000,
35  'reverted' => 30000
36  ];
37 
38  private const DEPRECATED_COUNT_TYPES = [
39  'anonedits' => 'anonymous',
40  'botedits' => 'bot',
41  'revertededits' => 'reverted'
42  ];
43 
44  private const MAX_AGE_200 = 60;
45 
46  private const REVERTED_TAG_NAMES = [ 'mw-undo', 'mw-rollback' ];
47 
49  private $revisionStore;
50 
53 
56 
58  private $loadBalancer;
59 
61  private $cache;
62 
64  private $user;
65 
67  private $revision;
68 
71 
73  private $titleObject;
74 
82  public function __construct(
84  NameTableStoreFactory $nameTableStoreFactory,
88  ) {
89  $this->revisionStore = $revisionStore;
90  $this->changeTagDefStore = $nameTableStoreFactory->getChangeTagDef();
91  $this->permissionManager = $permissionManager;
92  $this->loadBalancer = $loadBalancer;
93  $this->cache = $cache;
94 
95  // @todo Inject this, when there is a good way to do that
96  $this->user = RequestContext::getMain()->getUser();
97  }
98 
99  private function normalizeType( $type ) {
100  return self::DEPRECATED_COUNT_TYPES[$type] ?? $type;
101  }
102 
109  private function validateParameterCombination( $type ) {
110  $params = $this->getValidatedParams();
111  if ( !$params ) {
112  return;
113  }
114 
115  if ( $params['from'] || $params['to'] ) {
116  if ( $type === 'edits' || $type === 'editors' ) {
117  if ( !$params['from'] || !$params['to'] ) {
118  throw new LocalizedHttpException(
119  new MessageValue( 'rest-pagehistorycount-parameters-invalid' ),
120  400
121  );
122  }
123  } else {
124  throw new LocalizedHttpException(
125  new MessageValue( 'rest-pagehistorycount-parameters-invalid' ),
126  400
127  );
128  }
129  }
130  }
131 
138  public function run( $title, $type ) {
139  $normalizedType = $this->normalizeType( $type );
140  $this->validateParameterCombination( $normalizedType );
141  $titleObj = $this->getTitle();
142  if ( !$titleObj || !$titleObj->getArticleID() ) {
143  throw new LocalizedHttpException(
144  new MessageValue( 'rest-nonexistent-title',
145  [ new ScalarParam( ParamType::PLAINTEXT, $title ) ]
146  ),
147  404
148  );
149  }
150 
151  if ( !$this->permissionManager->userCan( 'read', $this->user, $titleObj ) ) {
152  throw new LocalizedHttpException(
153  new MessageValue( 'rest-permission-denied-title',
154  [ new ScalarParam( ParamType::PLAINTEXT, $title ) ]
155  ),
156  403
157  );
158  }
159 
160  $count = $this->getCount( $normalizedType );
161  $countLimit = self::COUNT_LIMITS[$normalizedType];
162  $response = $this->getResponseFactory()->createJson( [
163  'count' => $count > $countLimit ? $countLimit : $count,
164  'limit' => $count > $countLimit
165  ] );
166  $response->setHeader( 'Cache-Control', 'max-age=' . self::MAX_AGE_200 );
167 
168  // Inform clients who use a deprecated "type" value, so they can adjust
169  if ( isset( self::DEPRECATED_COUNT_TYPES[$type] ) ) {
170  $docs = '<https://www.mediawiki.org/wiki/API:REST/History_API' .
171  '#Get_page_history_counts>; rel="deprecation"';
172  $response->setHeader( 'Deprecation', 'version="v1"' );
173  $response->setHeader( 'Link', $docs );
174  }
175 
176  return $response;
177  }
178 
184  private function getCount( $type ) {
185  $pageId = $this->getTitle()->getArticleID();
186  switch ( $type ) {
187  case 'anonymous':
188  return $this->getCachedCount( $type,
189  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
190  return $this->getAnonCount( $pageId, $fromRev );
191  }
192  );
193 
194  case 'bot':
195  return $this->getCachedCount( $type,
196  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
197  return $this->getBotCount( $pageId, $fromRev );
198  }
199  );
200 
201  case 'editors':
202  $from = $this->getValidatedParams()['from'] ?? null;
203  $to = $this->getValidatedParams()['to'] ?? null;
204  if ( $from || $to ) {
205  return $this->getEditorsCount(
206  $pageId,
207  $from ? $this->getRevisionOrThrow( $from ) : null,
208  $to ? $this->getRevisionOrThrow( $to ) : null
209  );
210  } else {
211  return $this->getCachedCount( $type,
212  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
213  return $this->getEditorsCount( $pageId, $fromRev );
214  } );
215  }
216 
217  case 'edits':
218  $from = $this->getValidatedParams()['from'] ?? null;
219  $to = $this->getValidatedParams()['to'] ?? null;
220  if ( $from || $to ) {
221  return $this->getEditsCount(
222  $pageId,
223  $from ? $this->getRevisionOrThrow( $from ) : null,
224  $to ? $this->getRevisionOrThrow( $to ) : null
225  );
226  } else {
227  return $this->getCachedCount( $type,
228  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
229  return $this->getEditsCount( $pageId, $fromRev );
230  }
231  );
232  }
233 
234  case 'reverted':
235  return $this->getCachedCount( $type,
236  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
237  return $this->getRevertedCount( $pageId, $fromRev );
238  }
239  );
240 
241  case 'minor':
242  // The query for minor counts is inefficient for the database for pages with many revisions.
243  // If the specified title contains more revisions than allowed, we will return an error.
244  $editsCount = $this->getCachedCount( 'edits',
245  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
246  return $this->getEditsCount( $pageId, $fromRev );
247  }
248  );
249  if ( $editsCount > self::COUNT_LIMITS[$type] * 2 ) {
250  throw new LocalizedHttpException(
251  new MessageValue( 'rest-pagehistorycount-too-many-revisions' ),
252  500
253  );
254  }
255  return $this->getCachedCount( $type,
256  function ( RevisionRecord $fromRev = null ) use ( $pageId ) {
257  return $this->getMinorCount( $pageId, $fromRev );
258  }
259  );
260 
261  // Sanity check
262  default:
263  throw new LocalizedHttpException(
264  new MessageValue( 'rest-pagehistorycount-type-unrecognized',
265  [ new ScalarParam( ParamType::PLAINTEXT, $type ) ]
266  ),
267  500
268  );
269  }
270  }
271 
275  private function getCurrentRevision() {
276  if ( $this->revision === null ) {
277  $title = $this->getTitle();
278  if ( $title && $title->getArticleID() ) {
279  $this->revision = $this->revisionStore->getKnownCurrentRevision( $title );
280  } else {
281  $this->revision = false;
282  }
283  }
284  return $this->revision;
285  }
286 
290  private function getTitle() {
291  if ( $this->titleObject === null ) {
292  $this->titleObject = Title::newFromText( $this->getValidatedParams()['title'] );
293  }
294  return $this->titleObject;
295  }
296 
303  protected function getLastModified() {
305  if ( $lastModifiedTimes ) {
306  return max( array_values( $lastModifiedTimes ) );
307  }
308  }
309 
316  protected function getLastModifiedTimes() {
317  $currentRev = $this->getCurrentRevision();
318  if ( !$currentRev ) {
319  return null;
320  }
321  if ( $this->lastModifiedTimes === null ) {
322  $currentRevTime = (int)wfTimestampOrNull( TS_UNIX, $currentRev->getTimestamp() );
323  $loggingTableTime = $this->loggingTableTime( $currentRev->getPageId() );
324  $this->lastModifiedTimes = [
325  'currentRevTS' => $currentRevTime,
326  'dependencyModTS' => $loggingTableTime
327  ];
328  }
330  }
331 
337  private function loggingTableTime( $pageId ) {
338  $res = $this->loadBalancer->getConnectionRef( DB_REPLICA )->selectField(
339  'logging',
340  'MAX(log_timestamp)',
341  [ 'log_page' => $pageId ],
342  __METHOD__
343  );
344  return $res ? (int)wfTimestamp( TS_UNIX, $res ) : null;
345  }
346 
357  protected function getEtag() {
358  return null;
359  }
360 
366  private function getCachedCount( $type,
367  callable $fetchCount
368  ) {
369  $titleObj = $this->getTitle();
370  $pageId = $titleObj->getArticleID();
371  return $this->cache->getWithSetCallback(
372  $this->cache->makeKey( 'rest', 'pagehistorycount', $pageId, $type ),
373  WANObjectCache::TTL_WEEK,
374  function ( $oldValue ) use ( $fetchCount ) {
375  $currentRev = $this->getCurrentRevision();
376  if ( $oldValue ) {
377  // Last modified timestamp was NOT a dependency change (e.g. revdel)
378  $doIncrementalUpdate = (
379  $this->getLastModified() != $this->getLastModifiedTimes()['dependencyModTS']
380  );
381  if ( $doIncrementalUpdate ) {
382  $rev = $this->revisionStore->getRevisionById( $oldValue['revision'] );
383  if ( $rev ) {
384  $additionalCount = $fetchCount( $rev );
385  return [
386  'revision' => $currentRev->getId(),
387  'count' => $oldValue['count'] + $additionalCount,
388  'dependencyModTS' => $this->getLastModifiedTimes()['dependencyModTS']
389  ];
390  }
391  }
392  }
393  // Nothing was previously stored, or incremental update was done for too long,
394  // recalculate from scratch.
395  return [
396  'revision' => $currentRev->getId(),
397  'count' => $fetchCount(),
398  'dependencyModTS' => $this->getLastModifiedTimes()['dependencyModTS']
399  ];
400  },
401  [
402  'touchedCallback' => function (){
403  return $this->getLastModified();
404  },
405  'version' => 2,
406  'lockTSE' => WANObjectCache::TTL_MINUTE * 5
407  ]
408  )['count'];
409  }
410 
416  protected function getAnonCount( $pageId, RevisionRecord $fromRev = null ) {
417  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
418 
419  $cond = [
420  'rev_page' => $pageId,
421  'actor_user IS NULL',
422  $dbr->bitAnd( 'rev_deleted',
423  RevisionRecord::DELETED_TEXT | RevisionRecord::DELETED_USER ) . " = 0"
424  ];
425 
426  if ( $fromRev ) {
427  $oldTs = $dbr->addQuotes( $dbr->timestamp( $fromRev->getTimestamp() ) );
428  $cond[] = "(rev_timestamp = {$oldTs} AND rev_id > {$fromRev->getId()}) " .
429  "OR rev_timestamp > {$oldTs}";
430  }
431 
432  $edits = $dbr->selectRowCount(
433  [
434  'revision_actor_temp',
435  'revision',
436  'actor'
437  ],
438  '1',
439  $cond,
440  __METHOD__,
441  [ 'LIMIT' => self::COUNT_LIMITS['anonymous'] + 1 ], // extra to detect truncation
442  [
443  'revision' => [
444  'JOIN',
445  'revactor_rev = rev_id AND revactor_page = rev_page'
446  ],
447  'actor' => [
448  'JOIN',
449  'revactor_actor = actor_id'
450  ]
451  ]
452  );
453  return $edits;
454  }
455 
461  protected function getBotCount( $pageId, RevisionRecord $fromRev = null ) {
462  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
463 
464  $cond = [
465  'rev_page=' . intval( $pageId ),
466  $dbr->bitAnd( 'rev_deleted',
467  RevisionRecord::DELETED_TEXT | RevisionRecord::DELETED_USER ) . " = 0",
468  'EXISTS(' .
469  $dbr->selectSQLText(
470  'user_groups',
471  '1',
472  [
473  'actor.actor_user = ug_user',
474  'ug_group' => $this->permissionManager->getGroupsWithPermission( 'bot' ),
475  'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() )
476  ],
477  __METHOD__
478  ) .
479  ')'
480  ];
481  if ( $fromRev ) {
482  $oldTs = $dbr->addQuotes( $dbr->timestamp( $fromRev->getTimestamp() ) );
483  $cond[] = "(rev_timestamp = {$oldTs} AND rev_id > {$fromRev->getId()}) " .
484  "OR rev_timestamp > {$oldTs}";
485  }
486 
487  $edits = $dbr->selectRowCount(
488  [
489  'revision_actor_temp',
490  'revision',
491  'actor',
492  ],
493  '1',
494  $cond,
495  __METHOD__,
496  [ 'LIMIT' => self::COUNT_LIMITS['bot'] + 1 ], // extra to detect truncation
497  [
498  'revision' => [
499  'JOIN',
500  'revactor_rev = rev_id AND revactor_page = rev_page'
501  ],
502  'actor' => [
503  'JOIN',
504  'revactor_actor = actor_id'
505  ],
506  ]
507  );
508  return $edits;
509  }
510 
517  protected function getEditorsCount( $pageId,
518  RevisionRecord $fromRev = null,
519  RevisionRecord $toRev = null
520  ) {
521  list( $fromRev, $toRev ) = $this->orderRevisions( $fromRev, $toRev );
522  return $this->revisionStore->countAuthorsBetween( $pageId, $fromRev,
523  $toRev, $this->user, self::COUNT_LIMITS['editors'] );
524  }
525 
531  protected function getRevertedCount( $pageId, RevisionRecord $fromRev = null ) {
532  $tagIds = [];
533 
534  foreach ( self::REVERTED_TAG_NAMES as $tagName ) {
535  try {
536  $tagIds[] = $this->changeTagDefStore->getId( $tagName );
537  } catch ( NameTableAccessException $e ) {
538  // If no revisions are tagged with a name, no tag id will be present
539  }
540  }
541  if ( !$tagIds ) {
542  return 0;
543  }
544 
545  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
546 
547  $cond = [
548  'rev_page' => $pageId,
549  $dbr->bitAnd( 'rev_deleted', RevisionRecord::DELETED_TEXT ) . " = 0"
550  ];
551  if ( $fromRev ) {
552  $oldTs = $dbr->addQuotes( $dbr->timestamp( $fromRev->getTimestamp() ) );
553  $cond[] = "(rev_timestamp = {$oldTs} AND rev_id > {$fromRev->getId()}) " .
554  "OR rev_timestamp > {$oldTs}";
555  }
556  $edits = $dbr->selectRowCount(
557  [
558  'revision',
559  'change_tag'
560  ],
561  '1',
562  [ 'rev_page' => $pageId ],
563  __METHOD__,
564  [
565  'LIMIT' => self::COUNT_LIMITS['reverted'] + 1, // extra to detect truncation
566  'GROUP BY' => 'rev_id'
567  ],
568  [
569  'change_tag' => [
570  'JOIN',
571  [
572  'ct_rev_id = rev_id',
573  'ct_tag_id' => $tagIds,
574  ]
575  ],
576  ]
577  );
578  return $edits;
579  }
580 
586  protected function getMinorCount( $pageId, RevisionRecord $fromRev = null ) {
587  $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA );
588  $cond = [
589  'rev_page' => $pageId,
590  'rev_minor_edit != 0',
591  $dbr->bitAnd( 'rev_deleted', RevisionRecord::DELETED_TEXT ) . " = 0"
592  ];
593  if ( $fromRev ) {
594  $oldTs = $dbr->addQuotes( $dbr->timestamp( $fromRev->getTimestamp() ) );
595  $cond[] = "(rev_timestamp = {$oldTs} AND rev_id > {$fromRev->getId()}) " .
596  "OR rev_timestamp > {$oldTs}";
597  }
598  $edits = $dbr->selectRowCount( 'revision', '1',
599  $cond,
600  __METHOD__,
601  [ 'LIMIT' => self::COUNT_LIMITS['minor'] + 1 ] // extra to detect truncation
602  );
603 
604  return $edits;
605  }
606 
613  protected function getEditsCount(
614  $pageId,
615  RevisionRecord $fromRev = null,
616  RevisionRecord $toRev = null
617  ) {
618  list( $fromRev, $toRev ) = $this->orderRevisions( $fromRev, $toRev );
619  return $this->revisionStore->countRevisionsBetween(
620  $pageId,
621  $fromRev,
622  $toRev,
623  self::COUNT_LIMITS['edits'] // Will be increased by 1 to detect truncation
624  );
625  }
626 
632  private function getRevisionOrThrow( $revId ) {
633  $rev = $this->revisionStore->getRevisionById( $revId );
634  if ( !$rev ) {
635  throw new LocalizedHttpException(
636  new MessageValue( 'rest-nonexistent-revision', [ $revId ] ),
637  404
638  );
639  }
640  return $rev;
641  }
642 
650  private function orderRevisions(
651  RevisionRecord $fromRev = null,
652  RevisionRecord $toRev = null
653  ) {
654  if ( $fromRev && $toRev && ( $fromRev->getTimestamp() > $toRev->getTimestamp() ||
655  ( $fromRev->getTimestamp() === $toRev->getTimestamp()
656  && $fromRev->getId() > $toRev->getId() ) )
657  ) {
658  return [ $toRev, $fromRev ];
659  }
660  return [ $fromRev, $toRev ];
661  }
662 
663  public function needsWriteAccess() {
664  return false;
665  }
666 
667  public function getParamSettings() {
668  return [
669  'title' => [
670  self::PARAM_SOURCE => 'path',
671  ParamValidator::PARAM_TYPE => 'string',
672  ParamValidator::PARAM_REQUIRED => true,
673  ],
674  'type' => [
675  self::PARAM_SOURCE => 'path',
676  ParamValidator::PARAM_TYPE => array_merge(
677  array_keys( self::COUNT_LIMITS ),
678  array_keys( self::DEPRECATED_COUNT_TYPES )
679  ),
680  ParamValidator::PARAM_REQUIRED => true,
681  ],
682  'from' => [
683  self::PARAM_SOURCE => 'query',
684  ParamValidator::PARAM_TYPE => 'integer',
685  ParamValidator::PARAM_REQUIRED => false
686  ],
687  'to' => [
688  self::PARAM_SOURCE => 'query',
689  ParamValidator::PARAM_TYPE => 'integer',
690  ParamValidator::PARAM_REQUIRED => false
691  ]
692  ];
693  }
694 }
MediaWiki\Rest\Handler\PageHistoryCountHandler\$revisionStore
RevisionStore $revisionStore
Definition: PageHistoryCountHandler.php:49
MediaWiki\Rest\Handler\PageHistoryCountHandler\run
run( $title, $type)
Definition: PageHistoryCountHandler.php:138
MediaWiki\Rest\Handler\PageHistoryCountHandler\$titleObject
Title $titleObject
Definition: PageHistoryCountHandler.php:73
MediaWiki\Rest\Handler
Definition: ActionModuleBasedHandler.php:3
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:332
MediaWiki\Rest\Handler\PageHistoryCountHandler\$cache
WANObjectCache $cache
Definition: PageHistoryCountHandler.php:61
Revision\RevisionRecord
Page revision base class.
Definition: RevisionRecord.php:46
MediaWiki\Rest\Handler\PageHistoryCountHandler\getBotCount
getBotCount( $pageId, RevisionRecord $fromRev=null)
Definition: PageHistoryCountHandler.php:461
MediaWiki\Rest\Handler\getResponseFactory
getResponseFactory()
Get the ResponseFactory which can be used to generate Response objects.
Definition: Handler.php:92
$response
$response
Definition: opensearch_desc.php:44
Revision\RevisionStore
Service for looking up page revisions.
Definition: RevisionStore.php:77
MediaWiki\Rest\Handler\PageHistoryCountHandler\REVERTED_TAG_NAMES
const REVERTED_TAG_NAMES
Definition: PageHistoryCountHandler.php:46
MediaWiki\Rest\Handler\PageHistoryCountHandler\getEditsCount
getEditsCount( $pageId, RevisionRecord $fromRev=null, RevisionRecord $toRev=null)
Definition: PageHistoryCountHandler.php:613
wfTimestamp
wfTimestamp( $outputtype=TS_UNIX, $ts=0)
Get a timestamp string in one of various formats.
Definition: GlobalFunctions.php:1809
MediaWiki\Rest\Handler\PageHistoryCountHandler\getAnonCount
getAnonCount( $pageId, RevisionRecord $fromRev=null)
Definition: PageHistoryCountHandler.php:416
MediaWiki\Rest\Handler\PageHistoryCountHandler\$revision
RevisionRecord bool $revision
Definition: PageHistoryCountHandler.php:67
MediaWiki\Rest\Handler\PageHistoryCountHandler\getParamSettings
getParamSettings()
Fetch ParamValidator settings for parameters.
Definition: PageHistoryCountHandler.php:667
MediaWiki\Rest\Handler\PageHistoryCountHandler\__construct
__construct(RevisionStore $revisionStore, NameTableStoreFactory $nameTableStoreFactory, PermissionManager $permissionManager, ILoadBalancer $loadBalancer, WANObjectCache $cache)
Definition: PageHistoryCountHandler.php:82
MediaWiki\Rest\Handler\PageHistoryCountHandler\COUNT_LIMITS
const COUNT_LIMITS
The maximum number of counts to return per type of revision.
Definition: PageHistoryCountHandler.php:29
MediaWiki\Rest\Handler\PageHistoryCountHandler\getLastModifiedTimes
getLastModifiedTimes()
Returns array with 2 timestamps:
Definition: PageHistoryCountHandler.php:316
Wikimedia\Message\ScalarParam
Value object representing a message parameter holding a single value.
Definition: ScalarParam.php:10
$res
$res
Definition: testCompression.php:57
MediaWiki\Rest\Handler\PageHistoryCountHandler\$changeTagDefStore
NameTableStore $changeTagDefStore
Definition: PageHistoryCountHandler.php:52
MediaWiki\Rest\Handler\PageHistoryCountHandler\getEtag
getEtag()
Choosing to not implement etags in this handler.
Definition: PageHistoryCountHandler.php:357
Wikimedia\Message\MessageValue
Value object representing a message for i18n.
Definition: MessageValue.php:14
$dbr
$dbr
Definition: testCompression.php:54
MediaWiki\Rest\Handler\PageHistoryCountHandler\getLastModified
getLastModified()
Returns latest of 2 timestamps:
Definition: PageHistoryCountHandler.php:303
MediaWiki\Rest\Handler\PageHistoryCountHandler\validateParameterCombination
validateParameterCombination( $type)
Validates that the provided parameter combination is supported.
Definition: PageHistoryCountHandler.php:109
MediaWiki\Rest\Handler\PageHistoryCountHandler\DEPRECATED_COUNT_TYPES
const DEPRECATED_COUNT_TYPES
Definition: PageHistoryCountHandler.php:38
MediaWiki\Rest\Handler\PageHistoryCountHandler\getRevisionOrThrow
getRevisionOrThrow( $revId)
Definition: PageHistoryCountHandler.php:632
MediaWiki\Rest\Handler\PageHistoryCountHandler\$permissionManager
PermissionManager $permissionManager
Definition: PageHistoryCountHandler.php:55
MediaWiki\Rest\Handler\PageHistoryCountHandler\getRevertedCount
getRevertedCount( $pageId, RevisionRecord $fromRev=null)
Definition: PageHistoryCountHandler.php:531
MediaWiki\Rest\Handler\PageHistoryCountHandler
Handler class for Core REST API endpoints that perform operations on revisions.
Definition: PageHistoryCountHandler.php:27
MediaWiki\Rest\Handler\PageHistoryCountHandler\orderRevisions
orderRevisions(RevisionRecord $fromRev=null, RevisionRecord $toRev=null)
Reorders revisions if they are present.
Definition: PageHistoryCountHandler.php:650
MediaWiki\Rest\Handler\PageHistoryCountHandler\getEditorsCount
getEditorsCount( $pageId, RevisionRecord $fromRev=null, RevisionRecord $toRev=null)
Definition: PageHistoryCountHandler.php:517
MediaWiki\Rest\Handler\PageHistoryCountHandler\getTitle
getTitle()
Definition: PageHistoryCountHandler.php:290
wfTimestampOrNull
wfTimestampOrNull( $outputtype=TS_UNIX, $ts=null)
Return a formatted timestamp, or null if input is null.
Definition: GlobalFunctions.php:1825
MediaWiki\Rest\Handler\PageHistoryCountHandler\getMinorCount
getMinorCount( $pageId, RevisionRecord $fromRev=null)
Definition: PageHistoryCountHandler.php:586
MediaWiki\Rest\Response
Definition: Response.php:8
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
RequestContext
Group all the pieces relevant to the context of a request into one instance.
Definition: RequestContext.php:34
MediaWiki\Rest\Handler\getValidatedParams
getValidatedParams()
Fetch the validated parameters.
Definition: Handler.php:188
MediaWiki\Rest\Handler\PageHistoryCountHandler\$lastModifiedTimes
array $lastModifiedTimes
Definition: PageHistoryCountHandler.php:70
MediaWiki\Rest\Handler\PageHistoryCountHandler\$user
User $user
Definition: PageHistoryCountHandler.php:64
MediaWiki\Permissions\PermissionManager
A service class for checking permissions To obtain an instance, use MediaWikiServices::getInstance()-...
Definition: PermissionManager.php:48
WANObjectCache
Multi-datacenter aware caching interface.
Definition: WANObjectCache.php:118
MediaWiki\Storage\NameTableStore
Definition: NameTableStore.php:36
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:451
MediaWiki\Rest\Handler\PageHistoryCountHandler\getCount
getCount( $type)
Definition: PageHistoryCountHandler.php:184
MediaWiki\Rest\Handler\PageHistoryCountHandler\$loadBalancer
ILoadBalancer $loadBalancer
Definition: PageHistoryCountHandler.php:58
MediaWiki\Storage\NameTableStoreFactory\getChangeTagDef
getChangeTagDef( $wiki=false)
Get a NameTableStore for the change_tag_def table.
Definition: NameTableStoreFactory.php:127
Title
Represents a title within MediaWiki.
Definition: Title.php:42
MediaWiki\Rest\Handler\PageHistoryCountHandler\loggingTableTime
loggingTableTime( $pageId)
Return timestamp of latest entry in logging table for given page id.
Definition: PageHistoryCountHandler.php:337
MediaWiki\Storage\NameTableAccessException
Exception representing a failure to look up a row from a name table.
Definition: NameTableAccessException.php:32
MediaWiki\Storage\NameTableStoreFactory
Definition: NameTableStoreFactory.php:26
MediaWiki\Rest\Handler\PageHistoryCountHandler\needsWriteAccess
needsWriteAccess()
Indicates whether this route requires write access.
Definition: PageHistoryCountHandler.php:663
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:53
MediaWiki\Rest\Handler\PageHistoryCountHandler\getCachedCount
getCachedCount( $type, callable $fetchCount)
Definition: PageHistoryCountHandler.php:366
MediaWiki\Rest\Handler\PageHistoryCountHandler\normalizeType
normalizeType( $type)
Definition: PageHistoryCountHandler.php:99
Wikimedia\ParamValidator\ParamValidator
Service for formatting and validating API parameters.
Definition: ParamValidator.php:42
Wikimedia\Rdbms\ILoadBalancer
Database cluster connection, tracking, load balancing, and transaction manager interface.
Definition: ILoadBalancer.php:81
MediaWiki\Rest\LocalizedHttpException
Definition: LocalizedHttpException.php:7
Wikimedia\Message\ParamType
The constants used to specify parameter types.
Definition: ParamType.php:11
MediaWiki\Rest\Handler\PageHistoryCountHandler\getCurrentRevision
getCurrentRevision()
Definition: PageHistoryCountHandler.php:275
MediaWiki\Rest\SimpleHandler
Definition: SimpleHandler.php:14
$type
$type
Definition: testCompression.php:52
MediaWiki\Rest\Handler\PageHistoryCountHandler\MAX_AGE_200
const MAX_AGE_200
Definition: PageHistoryCountHandler.php:44