MediaWiki  1.30.0
SiteStats.php
Go to the documentation of this file.
1 <?php
26 
30 class SiteStats {
32  private static $row;
33 
35  private static $loaded = false;
36 
38  private static $pageCount = [];
39 
40  static function unload() {
41  self::$loaded = false;
42  }
43 
44  static function recache() {
45  self::load( true );
46  }
47 
51  static function load( $recache = false ) {
52  if ( self::$loaded && !$recache ) {
53  return;
54  }
55 
56  self::$row = self::loadAndLazyInit();
57 
58  # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
59  if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
60  # Update schema
61  $u = new SiteStatsUpdate( 0, 0, 0 );
62  $u->doUpdate();
63  self::$row = self::doLoad( wfGetDB( DB_REPLICA ) );
64  }
65 
66  self::$loaded = true;
67  }
68 
72  static function loadAndLazyInit() {
74 
75  wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" );
77 
78  if ( !self::isSane( $row ) ) {
79  $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
80  if ( $lb->hasOrMadeRecentMasterChanges() ) {
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 
87  if ( !$wgMiserMode && !self::isSane( $row ) ) {
88  // Normally the site_stats table is initialized at install time.
89  // Some manual construction scenarios may leave the table empty or
90  // broken, however, for instance when importing from a dump into a
91  // clean schema with mwdumper.
92  wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
93 
95 
97  }
98 
99  if ( !self::isSane( $row ) ) {
100  wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
101  }
102 
103  return $row;
104  }
105 
110  static function doLoad( $db ) {
111  return $db->selectRow( 'site_stats', [
112  'ss_row_id',
113  'ss_total_edits',
114  'ss_good_articles',
115  'ss_total_pages',
116  'ss_users',
117  'ss_active_users',
118  'ss_images',
119  ], [], __METHOD__ );
120  }
121 
130  static function views() {
131  wfDeprecated( __METHOD__, '1.25' );
132  return 0;
133  }
134 
138  static function edits() {
139  self::load();
140  return self::$row->ss_total_edits;
141  }
142 
146  static function articles() {
147  self::load();
148  return self::$row->ss_good_articles;
149  }
150 
154  static function pages() {
155  self::load();
156  return self::$row->ss_total_pages;
157  }
158 
162  static function users() {
163  self::load();
164  return self::$row->ss_users;
165  }
166 
170  static function activeUsers() {
171  self::load();
172  return self::$row->ss_active_users;
173  }
174 
178  static function images() {
179  self::load();
180  return self::$row->ss_images;
181  }
182 
188  static function numberingroup( $group ) {
189  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
190  return $cache->getWithSetCallback(
191  $cache->makeKey( 'SiteStats', 'groupcounts', $group ),
192  $cache::TTL_HOUR,
193  function ( $oldValue, &$ttl, array &$setOpts ) use ( $group ) {
194  $dbr = wfGetDB( DB_REPLICA );
195 
196  $setOpts += Database::getCacheSetOptions( $dbr );
197 
198  return $dbr->selectField(
199  'user_groups',
200  'COUNT(*)',
201  [
202  'ug_group' => $group,
203  'ug_expiry IS NULL OR ug_expiry >= ' . $dbr->addQuotes( $dbr->timestamp() )
204  ],
205  __METHOD__
206  );
207  },
208  [ 'pcTTL' => $cache::TTL_PROC_LONG ]
209  );
210  }
211 
216  static function jobs() {
217  $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
218  return $cache->getWithSetCallback(
219  $cache->makeKey( 'SiteStats', 'jobscount' ),
220  $cache::TTL_MINUTE,
221  function ( $oldValue, &$ttl, array &$setOpts ) {
222  try{
223  $jobs = array_sum( JobQueueGroup::singleton()->getQueueSizes() );
224  } catch ( JobQueueError $e ) {
225  $jobs = 0;
226  }
227  return $jobs;
228  },
229  [ 'pcTTL' => $cache::TTL_PROC_LONG ]
230  );
231  }
232 
238  static function pagesInNs( $ns ) {
239  if ( !isset( self::$pageCount[$ns] ) ) {
240  $dbr = wfGetDB( DB_REPLICA );
241  self::$pageCount[$ns] = (int)$dbr->selectField(
242  'page',
243  'COUNT(*)',
244  [ 'page_namespace' => $ns ],
245  __METHOD__
246  );
247  }
248  return self::$pageCount[$ns];
249  }
250 
260  private static function isSane( $row ) {
261  if ( $row === false
262  || $row->ss_total_pages < $row->ss_good_articles
263  || $row->ss_total_edits < $row->ss_total_pages
264  ) {
265  return false;
266  }
267  // Now check for underflow/overflow
268  foreach ( [
269  'ss_total_edits',
270  'ss_good_articles',
271  'ss_total_pages',
272  'ss_users',
273  'ss_images',
274  ] as $member ) {
275  if ( $row->$member > 2000000000 || $row->$member < 0 ) {
276  return false;
277  }
278  }
279  return true;
280  }
281 }
282 
287 
288  // Database connection
289  private $db;
290 
291  // Various stats
292  private $mEdits = null, $mArticles = null, $mPages = null;
293  private $mUsers = null, $mFiles = null;
294 
300  public function __construct( $database = false ) {
301  if ( $database instanceof IDatabase ) {
302  $this->db = $database;
303  } elseif ( $database ) {
304  $this->db = wfGetDB( DB_MASTER );
305  } else {
306  $this->db = wfGetDB( DB_REPLICA, 'vslow' );
307  }
308  }
309 
314  public function edits() {
315  $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
316  $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
317  return $this->mEdits;
318  }
319 
324  public function articles() {
326 
327  $tables = [ 'page' ];
328  $conds = [
329  'page_namespace' => MWNamespace::getContentNamespaces(),
330  'page_is_redirect' => 0,
331  ];
332 
333  if ( $wgArticleCountMethod == 'link' ) {
334  $tables[] = 'pagelinks';
335  $conds[] = 'pl_from=page_id';
336  } elseif ( $wgArticleCountMethod == 'comma' ) {
337  // To make a correct check for this, we would need, for each page,
338  // to load the text, maybe uncompress it, maybe decode it and then
339  // check if there's one comma.
340  // But one thing we are sure is that if the page is empty, it can't
341  // contain a comma :)
342  $conds[] = 'page_len > 0';
343  }
344 
345  $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)',
346  $conds, __METHOD__ );
347  return $this->mArticles;
348  }
349 
354  public function pages() {
355  $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
356  return $this->mPages;
357  }
358 
363  public function users() {
364  $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
365  return $this->mUsers;
366  }
367 
372  public function files() {
373  $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
374  return $this->mFiles;
375  }
376 
387  public static function doAllAndCommit( $database, array $options = [] ) {
388  $options += [ 'update' => false, 'activeUsers' => false ];
389 
390  // Grab the object and count everything
391  $counter = new SiteStatsInit( $database );
392 
393  $counter->edits();
394  $counter->articles();
395  $counter->pages();
396  $counter->users();
397  $counter->files();
398 
399  $counter->refresh();
400 
401  // Count active users if need be
402  if ( $options['activeUsers'] ) {
404  }
405  }
406 
410  public function refresh() {
411  $values = [
412  'ss_row_id' => 1,
413  'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ),
414  'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ),
415  'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ),
416  'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ),
417  'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ),
418  ];
419 
420  $dbw = wfGetDB( DB_MASTER );
421  $dbw->upsert( 'site_stats', $values, [ 'ss_row_id' ], $values, __METHOD__ );
422  }
423 }
SiteStats\articles
static articles()
Definition: SiteStats.php:146
Wikimedia\Rdbms\Database
Relational database abstraction object.
Definition: Database.php:45
SiteStats\$loaded
static bool $loaded
Definition: SiteStats.php:35
false
processing should stop and the error should be shown to the user * false
Definition: hooks.txt:187
$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:988
SiteStats\users
static users()
Definition: SiteStats.php:162
SiteStatsInit\doAllAndCommit
static doAllAndCommit( $database, array $options=[])
Do all updates and commit them.
Definition: SiteStats.php:387
SiteStats\activeUsers
static activeUsers()
Definition: SiteStats.php:170
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:260
SiteStatsInit\articles
articles()
Count pages in article space(s)
Definition: SiteStats.php:324
SiteStatsInit\$mArticles
$mArticles
Definition: SiteStats.php:292
SiteStatsInit\pages
pages()
Count total pages.
Definition: SiteStats.php:354
SiteStats\pages
static pages()
Definition: SiteStats.php:154
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:188
SiteStats\load
static load( $recache=false)
Definition: SiteStats.php:51
MWNamespace\getContentNamespaces
static getContentNamespaces()
Get a list of all namespace indices which are considered to contain content.
Definition: MWNamespace.php:353
SiteStatsInit
Class designed for counting of stats.
Definition: SiteStats.php:286
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:178
SiteStatsInit\files
files()
Count total files.
Definition: SiteStats.php:372
SiteStatsInit\$mEdits
$mEdits
Definition: SiteStats.php:292
wfDeprecated
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
Definition: GlobalFunctions.php:1176
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2856
SiteStatsInit\$db
$db
Definition: SiteStats.php:289
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:72
JobQueueError
Definition: JobQueue.php:723
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:1047
SiteStats\unload
static unload()
Definition: SiteStats.php:40
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2141
SiteStats\pagesInNs
static pagesInNs( $ns)
Definition: SiteStats.php:238
SiteStats\jobs
static jobs()
Total number of jobs in the job queue.
Definition: SiteStats.php:216
SiteStatsInit\$mUsers
$mUsers
Definition: SiteStats.php:293
SiteStats
Static accessor class for site_stats and related things.
Definition: SiteStats.php:30
SiteStatsInit\users
users()
Count total users.
Definition: SiteStats.php:363
SiteStats\doLoad
static doLoad( $db)
Definition: SiteStats.php:110
SiteStatsInit\$mPages
$mPages
Definition: SiteStats.php:292
$wgMiserMode
$wgMiserMode
Disable database-intensive features.
Definition: DefaultSettings.php:2166
$dbr
if(! $regexes) $dbr
Definition: cleanup.php:94
$cache
$cache
Definition: mcc.php:33
$options
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped & $options
Definition: hooks.txt:1965
SiteStatsInit\$mFiles
$mFiles
Definition: SiteStats.php:293
SiteStatsInit\__construct
__construct( $database=false)
Definition: SiteStats.php:300
JobQueueGroup\singleton
static singleton( $wiki=false)
Definition: JobQueueGroup.php:72
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:38
SiteStatsInit\edits
edits()
Count the total number of edits.
Definition: SiteStats.php:314
SiteStats\views
static views()
Return the total number of page views.
Definition: SiteStats.php:130
$wgArticleCountMethod
$wgArticleCountMethod
Method used to determine if a page in a content namespace should be counted as a valid article.
Definition: DefaultSettings.php:4460
SiteStats\$row
static bool stdClass $row
Definition: SiteStats.php:32
MediaWikiServices
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 MediaWikiServices
Definition: injection.txt:23
SiteStatsInit\refresh
refresh()
Refresh site_stats.
Definition: SiteStats.php:410
SiteStats\recache
static recache()
Definition: SiteStats.php:44
SiteStats\edits
static edits()
Definition: SiteStats.php:138
array
the array() calling protocol came about after MediaWiki 1.4rc1.