MediaWiki  1.29.1
SiteStats.php
Go to the documentation of this file.
1 <?php
25 
29 class SiteStats {
31  private static $row;
32 
34  private static $loaded = false;
35 
37  private static $jobs;
38 
40  private static $pageCount = [];
41 
42  static function unload() {
43  self::$loaded = false;
44  }
45 
46  static function recache() {
47  self::load( true );
48  }
49 
53  static function load( $recache = false ) {
54  if ( self::$loaded && !$recache ) {
55  return;
56  }
57 
58  self::$row = self::loadAndLazyInit();
59 
60  # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
61  if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
62  # Update schema
63  $u = new SiteStatsUpdate( 0, 0, 0 );
64  $u->doUpdate();
65  self::$row = self::doLoad( wfGetDB( DB_REPLICA ) );
66  }
67 
68  self::$loaded = true;
69  }
70 
74  static function loadAndLazyInit() {
76 
77  wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" );
79 
80  if ( !self::isSane( $row ) ) {
81  // Might have just been initialized during this request? Underflow?
82  wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" );
84  }
85 
86  if ( !$wgMiserMode && !self::isSane( $row ) ) {
87  // Normally the site_stats table is initialized at install time.
88  // Some manual construction scenarios may leave the table empty or
89  // broken, however, for instance when importing from a dump into a
90  // clean schema with mwdumper.
91  wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
92 
94 
96  }
97 
98  if ( !self::isSane( $row ) ) {
99  wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
100  }
101  return $row;
102  }
103 
108  static function doLoad( $db ) {
109  return $db->selectRow( 'site_stats', [
110  'ss_row_id',
111  'ss_total_edits',
112  'ss_good_articles',
113  'ss_total_pages',
114  'ss_users',
115  'ss_active_users',
116  'ss_images',
117  ], [], __METHOD__ );
118  }
119 
128  static function views() {
129  wfDeprecated( __METHOD__, '1.25' );
130  return 0;
131  }
132 
136  static function edits() {
137  self::load();
138  return self::$row->ss_total_edits;
139  }
140 
144  static function articles() {
145  self::load();
146  return self::$row->ss_good_articles;
147  }
148 
152  static function pages() {
153  self::load();
154  return self::$row->ss_total_pages;
155  }
156 
160  static function users() {
161  self::load();
162  return self::$row->ss_users;
163  }
164 
168  static function activeUsers() {
169  self::load();
170  return self::$row->ss_active_users;
171  }
172 
176  static function images() {
177  self::load();
178  return self::$row->ss_images;
179  }
180 
186  static function numberingroup( $group ) {
188  return $cache->getWithSetCallback(
189  wfMemcKey( 'SiteStats', 'groupcounts', $group ),
190  $cache::TTL_HOUR,
191  function ( $oldValue, &$ttl, array &$setOpts ) use ( $group ) {
192  $dbr = wfGetDB( DB_REPLICA );
193 
194  $setOpts += Database::getCacheSetOptions( $dbr );
195 
196  return $dbr->selectField(
197  'user_groups',
198  'COUNT(*)',
199  [
200  'ug_group' => $group,
201  'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() )
202  ],
203  __METHOD__
204  );
205  },
206  [ 'pcTTL' => $cache::TTL_PROC_LONG ]
207  );
208  }
209 
213  static function jobs() {
214  if ( !isset( self::$jobs ) ) {
215  try{
216  self::$jobs = array_sum( JobQueueGroup::singleton()->getQueueSizes() );
217  } catch ( JobQueueError $e ) {
218  self::$jobs = 0;
219  }
224  if ( self::$jobs == 1 ) {
225  self::$jobs = 0;
226  }
227  }
228  return self::$jobs;
229  }
230 
236  static function pagesInNs( $ns ) {
237  if ( !isset( self::$pageCount[$ns] ) ) {
238  $dbr = wfGetDB( DB_REPLICA );
239  self::$pageCount[$ns] = (int)$dbr->selectField(
240  'page',
241  'COUNT(*)',
242  [ 'page_namespace' => $ns ],
243  __METHOD__
244  );
245  }
246  return self::$pageCount[$ns];
247  }
248 
258  private static function isSane( $row ) {
259  if ( $row === false
260  || $row->ss_total_pages < $row->ss_good_articles
261  || $row->ss_total_edits < $row->ss_total_pages
262  ) {
263  return false;
264  }
265  // Now check for underflow/overflow
266  foreach ( [
267  'ss_total_edits',
268  'ss_good_articles',
269  'ss_total_pages',
270  'ss_users',
271  'ss_images',
272  ] as $member ) {
273  if ( $row->$member > 2000000000 || $row->$member < 0 ) {
274  return false;
275  }
276  }
277  return true;
278  }
279 }
280 
285 
286  // Database connection
287  private $db;
288 
289  // Various stats
290  private $mEdits = null, $mArticles = null, $mPages = null;
291  private $mUsers = null, $mFiles = null;
292 
299  public function __construct( $database = false ) {
300  if ( $database instanceof IDatabase ) {
301  $this->db = $database;
302  } elseif ( $database ) {
303  $this->db = wfGetDB( DB_MASTER );
304  } else {
305  $this->db = wfGetDB( DB_REPLICA, 'vslow' );
306  }
307  }
308 
313  public function edits() {
314  $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
315  $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
316  return $this->mEdits;
317  }
318 
323  public function articles() {
324  global $wgArticleCountMethod;
325 
326  $tables = [ 'page' ];
327  $conds = [
328  'page_namespace' => MWNamespace::getContentNamespaces(),
329  'page_is_redirect' => 0,
330  ];
331 
332  if ( $wgArticleCountMethod == 'link' ) {
333  $tables[] = 'pagelinks';
334  $conds[] = 'pl_from=page_id';
335  } elseif ( $wgArticleCountMethod == 'comma' ) {
336  // To make a correct check for this, we would need, for each page,
337  // to load the text, maybe uncompress it, maybe decode it and then
338  // check if there's one comma.
339  // But one thing we are sure is that if the page is empty, it can't
340  // contain a comma :)
341  $conds[] = 'page_len > 0';
342  }
343 
344  $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)',
345  $conds, __METHOD__ );
346  return $this->mArticles;
347  }
348 
353  public function pages() {
354  $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
355  return $this->mPages;
356  }
357 
362  public function users() {
363  $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
364  return $this->mUsers;
365  }
366 
371  public function files() {
372  $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
373  return $this->mFiles;
374  }
375 
386  public static function doAllAndCommit( $database, array $options = [] ) {
387  $options += [ 'update' => false, 'activeUsers' => false ];
388 
389  // Grab the object and count everything
390  $counter = new SiteStatsInit( $database );
391 
392  $counter->edits();
393  $counter->articles();
394  $counter->pages();
395  $counter->users();
396  $counter->files();
397 
398  $counter->refresh();
399 
400  // Count active users if need be
401  if ( $options['activeUsers'] ) {
403  }
404  }
405 
409  public function refresh() {
410  $values = [
411  'ss_row_id' => 1,
412  'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ),
413  'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ),
414  'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ),
415  'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ),
416  'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ),
417  ];
418 
419  $dbw = wfGetDB( DB_MASTER );
420  $dbw->upsert( 'site_stats', $values, [ 'ss_row_id' ], $values, __METHOD__ );
421  }
422 }
SiteStats\articles
static articles()
Definition: SiteStats.php:144
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:45
SiteStats\$loaded
static bool $loaded
Definition: SiteStats.php:34
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:189
$tables
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist & $tables
Definition: hooks.txt:990
SiteStats\users
static users()
Definition: SiteStats.php:160
SiteStatsInit\doAllAndCommit
static doAllAndCommit( $database, array $options=[])
Do all updates and commit them.
Definition: SiteStats.php:386
SiteStats\activeUsers
static activeUsers()
Definition: SiteStats.php:168
SiteStatsUpdate\cacheUpdate
static cacheUpdate( $dbw)
Definition: SiteStatsUpdate.php:143
SiteStats\isSane
static isSane( $row)
Is the provided row of site stats sane, or should it be regenerated?
Definition: SiteStats.php:258
SiteStatsInit\articles
articles()
Count pages in article space(s)
Definition: SiteStats.php:323
SiteStatsInit\$mArticles
$mArticles
Definition: SiteStats.php:290
SiteStatsInit\pages
pages()
Count total pages.
Definition: SiteStats.php:353
SiteStats\pages
static pages()
Definition: SiteStats.php:152
use
as see the revision history and available at free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:10
SiteStats\numberingroup
static numberingroup( $group)
Find the number of users in a given user group.
Definition: SiteStats.php:186
SiteStats\load
static load( $recache=false)
Definition: SiteStats.php:53
MWNamespace\getContentNamespaces
static getContentNamespaces()
Get a list of all namespace indices which are considered to contain content.
Definition: MWNamespace.php:339
SiteStatsInit
Class designed for counting of stats.
Definition: SiteStats.php:284
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
Wikimedia\Rdbms\IDatabase
Basic database interface for live and lazy-loaded relation database handles.
Definition: IDatabase.php:40
SiteStats\images
static images()
Definition: SiteStats.php:176
SiteStatsInit\files
files()
Count total files.
Definition: SiteStats.php:371
wfMemcKey
wfMemcKey()
Make a cache key for the local wiki.
Definition: GlobalFunctions.php:2961
SiteStatsInit\$mEdits
$mEdits
Definition: SiteStats.php:290
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1128
SiteStats\$jobs
static int $jobs
Definition: SiteStats.php:37
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3060
SiteStatsInit\$db
$db
Definition: SiteStats.php:287
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
SiteStats\loadAndLazyInit
static loadAndLazyInit()
Definition: SiteStats.php:74
JobQueueError
Definition: JobQueue.php:724
SiteStatsUpdate
Class for handling updates to the site_stats table.
Definition: SiteStatsUpdate.php:27
DB_MASTER
const DB_MASTER
Definition: defines.php:26
wfDebug
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:999
SiteStats\unload
static unload()
Definition: SiteStats.php:42
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2122
SiteStats\pagesInNs
static pagesInNs( $ns)
Definition: SiteStats.php:236
SiteStats\jobs
static jobs()
Definition: SiteStats.php:213
SiteStatsInit\$mUsers
$mUsers
Definition: SiteStats.php:291
SiteStats
Static accessor class for site_stats and related things.
Definition: SiteStats.php:29
SiteStatsInit\users
users()
Count total users.
Definition: SiteStats.php:362
SiteStats\doLoad
static doLoad( $db)
Definition: SiteStats.php:108
SiteStatsInit\$mPages
$mPages
Definition: SiteStats.php:290
$wgMiserMode
$wgMiserMode
Disable database-intensive features.
Definition: DefaultSettings.php:2144
$dbr
if(! $regexes) $dbr
Definition: cleanup.php:94
$cache
$cache
Definition: mcc.php:33
SiteStatsInit\$mFiles
$mFiles
Definition: SiteStats.php:291
ObjectCache\getMainWANInstance
static getMainWANInstance()
Get the main WAN cache object.
Definition: ObjectCache.php:370
SiteStatsInit\__construct
__construct( $database=false)
Constructor.
Definition: SiteStats.php:299
JobQueueGroup\singleton
static singleton( $wiki=false)
Definition: JobQueueGroup.php:71
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
SiteStats\$pageCount
static int[] $pageCount
Definition: SiteStats.php:40
SiteStatsInit\edits
edits()
Count the total number of edits.
Definition: SiteStats.php:313
SiteStats\views
static views()
Return the total number of page views.
Definition: SiteStats.php:128
SiteStats\$row
static bool stdClass $row
Definition: SiteStats.php:31
SiteStatsInit\refresh
refresh()
Refresh site_stats.
Definition: SiteStats.php:409
$options
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1049
SiteStats\recache
static recache()
Definition: SiteStats.php:46
SiteStats\edits
static edits()
Definition: SiteStats.php:136
array
the array() calling protocol came about after MediaWiki 1.4rc1.