MediaWiki  1.23.13
SiteStats.php
Go to the documentation of this file.
1 <?php
26 class SiteStats {
27  static $row, $loaded = false;
28  static $jobs;
29  static $pageCount = array();
31 
32  static function recache() {
33  self::load( true );
34  }
35 
39  static function load( $recache = false ) {
40  if ( self::$loaded && !$recache ) {
41  return;
42  }
43 
44  self::$row = self::loadAndLazyInit();
45 
46  # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
47  if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
48  # Update schema
49  $u = new SiteStatsUpdate( 0, 0, 0 );
50  $u->doUpdate();
51  self::$row = self::doLoad( wfGetDB( DB_SLAVE ) );
52  }
53 
54  self::$loaded = true;
55  }
56 
60  static function loadAndLazyInit() {
61  wfDebug( __METHOD__ . ": reading site_stats from slave\n" );
63 
64  if ( !self::isSane( $row ) ) {
65  // Might have just been initialized during this request? Underflow?
66  wfDebug( __METHOD__ . ": site_stats damaged or missing on slave\n" );
68  }
69 
70  if ( !self::isSane( $row ) ) {
71  // Normally the site_stats table is initialized at install time.
72  // Some manual construction scenarios may leave the table empty or
73  // broken, however, for instance when importing from a dump into a
74  // clean schema with mwdumper.
75  wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
76 
78 
80  }
81 
82  if ( !self::isSane( $row ) ) {
83  wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
84  }
85  return $row;
86  }
87 
92  static function doLoad( $db ) {
93  return $db->selectRow( 'site_stats', array(
94  'ss_row_id',
95  'ss_total_views',
96  'ss_total_edits',
97  'ss_good_articles',
98  'ss_total_pages',
99  'ss_users',
100  'ss_active_users',
101  'ss_images',
102  ), false, __METHOD__ );
103  }
104 
108  static function views() {
109  self::load();
110  return self::$row->ss_total_views;
111  }
112 
116  static function edits() {
117  self::load();
118  return self::$row->ss_total_edits;
119  }
120 
124  static function articles() {
125  self::load();
126  return self::$row->ss_good_articles;
127  }
128 
132  static function pages() {
133  self::load();
134  return self::$row->ss_total_pages;
135  }
136 
140  static function users() {
141  self::load();
142  return self::$row->ss_users;
143  }
144 
148  static function activeUsers() {
149  self::load();
150  return self::$row->ss_active_users;
151  }
152 
156  static function images() {
157  self::load();
158  return self::$row->ss_images;
159  }
160 
166  static function numberingroup( $group ) {
167  if ( !isset( self::$groupMemberCounts[$group] ) ) {
168  global $wgMemc;
169  $key = wfMemcKey( 'SiteStats', 'groupcounts', $group );
170  $hit = $wgMemc->get( $key );
171  if ( !$hit ) {
172  $dbr = wfGetDB( DB_SLAVE );
173  $hit = $dbr->selectField(
174  'user_groups',
175  'COUNT(*)',
176  array( 'ug_group' => $group ),
177  __METHOD__
178  );
179  $wgMemc->set( $key, $hit, 3600 );
180  }
181  self::$groupMemberCounts[$group] = $hit;
182  }
183  return self::$groupMemberCounts[$group];
184  }
185 
189  static function jobs() {
190  if ( !isset( self::$jobs ) ) {
191  $dbr = wfGetDB( DB_SLAVE );
192  self::$jobs = array_sum( JobQueueGroup::singleton()->getQueueSizes() );
193  /* Zero rows still do single row read for row that doesn't exist, but people are annoyed by that */
194  if ( self::$jobs == 1 ) {
195  self::$jobs = 0;
196  }
197  }
198  return self::$jobs;
199  }
200 
206  static function pagesInNs( $ns ) {
207  wfProfileIn( __METHOD__ );
208  if ( !isset( self::$pageCount[$ns] ) ) {
209  $dbr = wfGetDB( DB_SLAVE );
210  self::$pageCount[$ns] = (int)$dbr->selectField(
211  'page',
212  'COUNT(*)',
213  array( 'page_namespace' => $ns ),
214  __METHOD__
215  );
216  }
217  wfProfileOut( __METHOD__ );
218  return self::$pageCount[$ns];
219  }
220 
230  private static function isSane( $row ) {
231  if ( $row === false
232  || $row->ss_total_pages < $row->ss_good_articles
233  || $row->ss_total_edits < $row->ss_total_pages
234  ) {
235  return false;
236  }
237  // Now check for underflow/overflow
238  foreach ( array(
239  'ss_total_views',
240  'ss_total_edits',
241  'ss_good_articles',
242  'ss_total_pages',
243  'ss_users',
244  'ss_images',
245  ) as $member ) {
246  if ( $row->$member > 2000000000 || $row->$member < 0 ) {
247  return false;
248  }
249  }
250  return true;
251  }
252 }
253 
258 
259  // Database connection
260  private $db;
261 
262  // Various stats
263  private $mEdits = null, $mArticles = null, $mPages = null;
264  private $mUsers = null, $mViews = null, $mFiles = null;
265 
272  public function __construct( $database = false ) {
273  if ( $database instanceof DatabaseBase ) {
274  $this->db = $database;
275  } else {
276  $this->db = wfGetDB( $database ? DB_MASTER : DB_SLAVE );
277  }
278  }
279 
284  public function edits() {
285  $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
286  $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
287  return $this->mEdits;
288  }
289 
294  public function articles() {
295  global $wgArticleCountMethod;
296 
297  $tables = array( 'page' );
298  $conds = array(
299  'page_namespace' => MWNamespace::getContentNamespaces(),
300  'page_is_redirect' => 0,
301  );
302 
303  if ( $wgArticleCountMethod == 'link' ) {
304  $tables[] = 'pagelinks';
305  $conds[] = 'pl_from=page_id';
306  } elseif ( $wgArticleCountMethod == 'comma' ) {
307  // To make a correct check for this, we would need, for each page,
308  // to load the text, maybe uncompress it, maybe decode it and then
309  // check if there's one comma.
310  // But one thing we are sure is that if the page is empty, it can't
311  // contain a comma :)
312  $conds[] = 'page_len > 0';
313  }
314 
315  $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)',
316  $conds, __METHOD__ );
317  return $this->mArticles;
318  }
319 
324  public function pages() {
325  $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
326  return $this->mPages;
327  }
328 
333  public function users() {
334  $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
335  return $this->mUsers;
336  }
337 
342  public function views() {
343  $this->mViews = $this->db->selectField( 'page', 'SUM(page_counter)', '', __METHOD__ );
344  return $this->mViews;
345  }
346 
351  public function files() {
352  $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
353  return $this->mFiles;
354  }
355 
367  public static function doAllAndCommit( $database, array $options = array() ) {
368  $options += array( 'update' => false, 'views' => true, 'activeUsers' => false );
369 
370  // Grab the object and count everything
371  $counter = new SiteStatsInit( $database );
372 
373  $counter->edits();
374  $counter->articles();
375  $counter->pages();
376  $counter->users();
377  $counter->files();
378 
379  // Only do views if we don't want to not count them
380  if ( $options['views'] ) {
381  $counter->views();
382  }
383 
384  $counter->refresh();
385 
386  // Count active users if need be
387  if ( $options['activeUsers'] ) {
389  }
390  }
391 
396  public function refresh() {
397  $values = array(
398  'ss_row_id' => 1,
399  'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ),
400  'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ),
401  'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ),
402  'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ),
403  'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ),
404  ) + (
405  $this->mViews ? array( 'ss_total_views' => $this->mViews ) : array()
406  );
407 
408  $dbw = wfGetDB( DB_MASTER );
409  $dbw->upsert( 'site_stats', $values, array( 'ss_row_id' ), $values, __METHOD__ );
410  }
411 }
SiteStats\articles
static articles()
Definition: SiteStats.php:124
DB_MASTER
const DB_MASTER
Definition: Defines.php:56
php
skin txt MediaWiki includes four core it has been set as the default in MediaWiki since the replacing Monobook it had been been the default skin since before being replaced by Vector largely rewritten in while keeping its appearance Several legacy skins were removed in the as the burden of supporting them became too heavy to bear Those in etc for skin dependent CSS etc for skin dependent JavaScript These can also be customised on a per user by etc This feature has led to a wide variety of user styles becoming that gallery is a good place to ending in php
Definition: skin.txt:62
SiteStats\users
static users()
Definition: SiteStats.php:140
$tables
namespace and then decline to actually register it RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist & $tables
Definition: hooks.txt:815
SiteStats\activeUsers
static activeUsers()
Definition: SiteStats.php:148
SiteStatsUpdate\cacheUpdate
static cacheUpdate( $dbw)
Definition: SiteStatsUpdate.php:129
$wgMemc
globals will be eliminated from MediaWiki replaced by an application object which would be passed to constructors Whether that would be an convenient solution remains to be but certainly PHP makes such object oriented programming models easier than they were in previous versions For the time being MediaWiki programmers will have to work in an environment with some global context At the time of globals were initialised on startup by MediaWiki of these were configuration which are documented in DefaultSettings php There is no comprehensive documentation for the remaining however some of the most important ones are listed below They are typically initialised either in index php or in Setup php For a description of the see design txt $wgTitle Title object created from the request URL $wgOut OutputPage object for HTTP response $wgUser User object for the user associated with the current request $wgLang Language object selected by user preferences $wgContLang Language object associated with the wiki being viewed $wgParser Parser object Parser extensions register their hooks here $wgRequest WebRequest to get request data $wgMemc
Definition: globals.txt:25
SiteStats\isSane
static isSane( $row)
Is the provided row of site stats sane, or should it be regenerated?
Definition: SiteStats.php:230
wfGetDB
& wfGetDB( $db, $groups=array(), $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:3706
SiteStatsInit\articles
articles()
Count pages in article space(s)
Definition: SiteStats.php:294
SiteStatsInit\$mArticles
$mArticles
Definition: SiteStats.php:263
SiteStatsInit\pages
pages()
Count total pages.
Definition: SiteStats.php:324
SiteStats\pages
static pages()
Definition: SiteStats.php:132
wfProfileIn
wfProfileIn( $functionname)
Begin profiling of a function.
Definition: Profiler.php:33
SiteStats\numberingroup
static numberingroup( $group)
Find the number of users in a given user group.
Definition: SiteStats.php:166
SiteStats\load
static load( $recache=false)
Definition: SiteStats.php:39
MWNamespace\getContentNamespaces
static getContentNamespaces()
Get a list of all namespace indices which are considered to contain content.
Definition: Namespace.php:334
SiteStatsInit\$mViews
$mViews
Definition: SiteStats.php:264
SiteStatsInit
Class designed for counting of stats.
Definition: SiteStats.php:257
SiteStatsInit\views
views()
Count views.
Definition: SiteStats.php:342
$dbr
$dbr
Definition: testCompression.php:48
SiteStats\images
static images()
Definition: SiteStats.php:156
SiteStatsInit\doAllAndCommit
static doAllAndCommit( $database, array $options=array())
Do all updates and commit them.
Definition: SiteStats.php:367
SiteStatsInit\files
files()
Count total files.
Definition: SiteStats.php:351
wfMemcKey
wfMemcKey()
Get a cache key.
Definition: GlobalFunctions.php:3627
SiteStatsInit\$mEdits
$mEdits
Definition: SiteStats.php:263
wfProfileOut
wfProfileOut( $functionname='missing')
Stop profiling of a function.
Definition: Profiler.php:46
SiteStats\$jobs
static $jobs
Definition: SiteStats.php:28
array
the array() calling protocol came about after MediaWiki 1.4rc1.
List of Api Query prop modules.
SiteStatsInit\$db
$db
Definition: SiteStats.php:260
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:93
SiteStats\loadAndLazyInit
static loadAndLazyInit()
Definition: SiteStats.php:60
SiteStatsUpdate
Class for handling updates to the site_stats table.
Definition: SiteStatsUpdate.php:24
$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:1530
SiteStats\$row
static $row
Definition: SiteStats.php:27
wfDebug
wfDebug( $text, $dest='all')
Sends a line to the debug log if enabled or, optionally, to a comment in output.
Definition: GlobalFunctions.php:980
SiteStats\pagesInNs
static pagesInNs( $ns)
Definition: SiteStats.php:206
DatabaseBase
Database abstraction object.
Definition: Database.php:219
SiteStats\jobs
static jobs()
Definition: SiteStats.php:189
SiteStatsInit\$mUsers
$mUsers
Definition: SiteStats.php:264
SiteStats
Static accessor class for site_stats and related things.
Definition: SiteStats.php:26
SiteStatsInit\users
users()
Count total users.
Definition: SiteStats.php:333
SiteStats\$loaded
static $loaded
Definition: SiteStats.php:27
SiteStats\doLoad
static doLoad( $db)
Definition: SiteStats.php:92
DB_SLAVE
const DB_SLAVE
Definition: Defines.php:55
SiteStatsInit\$mPages
$mPages
Definition: SiteStats.php:263
SiteStatsInit\$mFiles
$mFiles
Definition: SiteStats.php:264
SiteStatsInit\__construct
__construct( $database=false)
Constructor.
Definition: SiteStats.php:272
JobQueueGroup\singleton
static singleton( $wiki=false)
Definition: JobQueueGroup.php:61
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 $pageCount
Definition: SiteStats.php:29
SiteStatsInit\edits
edits()
Count the total number of edits.
Definition: SiteStats.php:284
SiteStats\views
static views()
Definition: SiteStats.php:108
SiteStatsInit\refresh
refresh()
Refresh site_stats.
Definition: SiteStats.php:396
SiteStats\$groupMemberCounts
static $groupMemberCounts
Definition: SiteStats.php:30
SiteStats\recache
static recache()
Definition: SiteStats.php:32
SiteStats\edits
static edits()
Definition: SiteStats.php:116