MediaWiki REL1_28
SiteStats.php
Go to the documentation of this file.
1<?php
26class SiteStats {
28 private static $row;
29
31 private static $loaded = false;
32
34 private static $jobs;
35
37 private static $pageCount = [];
38
39 static function unload() {
40 self::$loaded = false;
41 }
42
43 static function recache() {
44 self::load( true );
45 }
46
50 static function load( $recache = false ) {
51 if ( self::$loaded && !$recache ) {
52 return;
53 }
54
55 self::$row = self::loadAndLazyInit();
56
57 # This code is somewhat schema-agnostic, because I'm changing it in a minor release -- TS
58 if ( !isset( self::$row->ss_total_pages ) && self::$row->ss_total_pages == -1 ) {
59 # Update schema
60 $u = new SiteStatsUpdate( 0, 0, 0 );
61 $u->doUpdate();
62 self::$row = self::doLoad( wfGetDB( DB_REPLICA ) );
63 }
64
65 self::$loaded = true;
66 }
67
71 static function loadAndLazyInit() {
73
74 wfDebug( __METHOD__ . ": reading site_stats from replica DB\n" );
76
77 if ( !self::isSane( $row ) ) {
78 // Might have just been initialized during this request? Underflow?
79 wfDebug( __METHOD__ . ": site_stats damaged or missing on replica DB\n" );
81 }
82
83 if ( !$wgMiserMode && !self::isSane( $row ) ) {
84 // Normally the site_stats table is initialized at install time.
85 // Some manual construction scenarios may leave the table empty or
86 // broken, however, for instance when importing from a dump into a
87 // clean schema with mwdumper.
88 wfDebug( __METHOD__ . ": initializing damaged or missing site_stats\n" );
89
91
93 }
94
95 if ( !self::isSane( $row ) ) {
96 wfDebug( __METHOD__ . ": site_stats persistently nonsensical o_O\n" );
97 }
98 return $row;
99 }
100
105 static function doLoad( $db ) {
106 return $db->selectRow( 'site_stats', [
107 'ss_row_id',
108 'ss_total_edits',
109 'ss_good_articles',
110 'ss_total_pages',
111 'ss_users',
112 'ss_active_users',
113 'ss_images',
114 ], [], __METHOD__ );
115 }
116
125 static function views() {
126 wfDeprecated( __METHOD__, '1.25' );
127 return 0;
128 }
129
133 static function edits() {
134 self::load();
135 return self::$row->ss_total_edits;
136 }
137
141 static function articles() {
142 self::load();
143 return self::$row->ss_good_articles;
144 }
145
149 static function pages() {
150 self::load();
151 return self::$row->ss_total_pages;
152 }
153
157 static function users() {
158 self::load();
159 return self::$row->ss_users;
160 }
161
165 static function activeUsers() {
166 self::load();
167 return self::$row->ss_active_users;
168 }
169
173 static function images() {
174 self::load();
175 return self::$row->ss_images;
176 }
177
183 static function numberingroup( $group ) {
184 $cache = ObjectCache::getMainWANInstance();
185 return $cache->getWithSetCallback(
186 wfMemcKey( 'SiteStats', 'groupcounts', $group ),
187 $cache::TTL_HOUR,
188 function ( $oldValue, &$ttl, array &$setOpts ) use ( $group ) {
190
191 $setOpts += Database::getCacheSetOptions( $dbr );
192
193 return $dbr->selectField(
194 'user_groups',
195 'COUNT(*)',
196 [ 'ug_group' => $group ],
197 __METHOD__
198 );
199 },
200 [ 'pcTTL' => $cache::TTL_PROC_LONG ]
201 );
202 }
203
207 static function jobs() {
208 if ( !isset( self::$jobs ) ) {
209 try{
210 self::$jobs = array_sum( JobQueueGroup::singleton()->getQueueSizes() );
211 } catch ( JobQueueError $e ) {
212 self::$jobs = 0;
213 }
218 if ( self::$jobs == 1 ) {
219 self::$jobs = 0;
220 }
221 }
222 return self::$jobs;
223 }
224
230 static function pagesInNs( $ns ) {
231 if ( !isset( self::$pageCount[$ns] ) ) {
233 self::$pageCount[$ns] = (int)$dbr->selectField(
234 'page',
235 'COUNT(*)',
236 [ 'page_namespace' => $ns ],
237 __METHOD__
238 );
239 }
240 return self::$pageCount[$ns];
241 }
242
252 private static function isSane( $row ) {
253 if ( $row === false
254 || $row->ss_total_pages < $row->ss_good_articles
255 || $row->ss_total_edits < $row->ss_total_pages
256 ) {
257 return false;
258 }
259 // Now check for underflow/overflow
260 foreach ( [
261 'ss_total_edits',
262 'ss_good_articles',
263 'ss_total_pages',
264 'ss_users',
265 'ss_images',
266 ] as $member ) {
267 if ( $row->$member > 2000000000 || $row->$member < 0 ) {
268 return false;
269 }
270 }
271 return true;
272 }
273}
274
279
280 // Database connection
281 private $db;
282
283 // Various stats
284 private $mEdits = null, $mArticles = null, $mPages = null;
285 private $mUsers = null, $mFiles = null;
286
293 public function __construct( $database = false ) {
294 if ( $database instanceof IDatabase ) {
295 $this->db = $database;
296 } elseif ( $database ) {
297 $this->db = wfGetDB( DB_MASTER );
298 } else {
299 $this->db = wfGetDB( DB_REPLICA, 'vslow' );
300 }
301 }
302
307 public function edits() {
308 $this->mEdits = $this->db->selectField( 'revision', 'COUNT(*)', '', __METHOD__ );
309 $this->mEdits += $this->db->selectField( 'archive', 'COUNT(*)', '', __METHOD__ );
310 return $this->mEdits;
311 }
312
317 public function articles() {
319
320 $tables = [ 'page' ];
321 $conds = [
322 'page_namespace' => MWNamespace::getContentNamespaces(),
323 'page_is_redirect' => 0,
324 ];
325
326 if ( $wgArticleCountMethod == 'link' ) {
327 $tables[] = 'pagelinks';
328 $conds[] = 'pl_from=page_id';
329 } elseif ( $wgArticleCountMethod == 'comma' ) {
330 // To make a correct check for this, we would need, for each page,
331 // to load the text, maybe uncompress it, maybe decode it and then
332 // check if there's one comma.
333 // But one thing we are sure is that if the page is empty, it can't
334 // contain a comma :)
335 $conds[] = 'page_len > 0';
336 }
337
338 $this->mArticles = $this->db->selectField( $tables, 'COUNT(DISTINCT page_id)',
339 $conds, __METHOD__ );
340 return $this->mArticles;
341 }
342
347 public function pages() {
348 $this->mPages = $this->db->selectField( 'page', 'COUNT(*)', '', __METHOD__ );
349 return $this->mPages;
350 }
351
356 public function users() {
357 $this->mUsers = $this->db->selectField( 'user', 'COUNT(*)', '', __METHOD__ );
358 return $this->mUsers;
359 }
360
365 public function files() {
366 $this->mFiles = $this->db->selectField( 'image', 'COUNT(*)', '', __METHOD__ );
367 return $this->mFiles;
368 }
369
380 public static function doAllAndCommit( $database, array $options = [] ) {
381 $options += [ 'update' => false, 'activeUsers' => false ];
382
383 // Grab the object and count everything
384 $counter = new SiteStatsInit( $database );
385
386 $counter->edits();
387 $counter->articles();
388 $counter->pages();
389 $counter->users();
390 $counter->files();
391
392 $counter->refresh();
393
394 // Count active users if need be
395 if ( $options['activeUsers'] ) {
397 }
398 }
399
403 public function refresh() {
404 $values = [
405 'ss_row_id' => 1,
406 'ss_total_edits' => ( $this->mEdits === null ? $this->edits() : $this->mEdits ),
407 'ss_good_articles' => ( $this->mArticles === null ? $this->articles() : $this->mArticles ),
408 'ss_total_pages' => ( $this->mPages === null ? $this->pages() : $this->mPages ),
409 'ss_users' => ( $this->mUsers === null ? $this->users() : $this->mUsers ),
410 'ss_images' => ( $this->mFiles === null ? $this->files() : $this->mFiles ),
411 ];
412
413 $dbw = wfGetDB( DB_MASTER );
414 $dbw->upsert( 'site_stats', $values, [ 'ss_row_id' ], $values, __METHOD__ );
415 }
416}
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
$wgArticleCountMethod
Method used to determine if a page in a content namespace should be counted as a valid article.
$wgMiserMode
Disable database-intensive features.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
wfMemcKey()
Make a cache key for the local wiki.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
static singleton( $wiki=false)
Class designed for counting of stats.
edits()
Count the total number of edits.
pages()
Count total pages.
articles()
Count pages in article space(s)
static doAllAndCommit( $database, array $options=[])
Do all updates and commit them.
files()
Count total files.
refresh()
Refresh site_stats.
users()
Count total users.
__construct( $database=false)
Constructor.
Class for handling updates to the site_stats table.
static cacheUpdate( $dbw)
Static accessor class for site_stats and related things.
Definition SiteStats.php:26
static isSane( $row)
Is the provided row of site stats sane, or should it be regenerated?
static articles()
static jobs()
static pagesInNs( $ns)
static images()
static views()
Return the total number of page views.
static load( $recache=false)
Definition SiteStats.php:50
static edits()
static bool $loaded
Definition SiteStats.php:31
static loadAndLazyInit()
Definition SiteStats.php:71
static bool stdClass $row
Definition SiteStats.php:28
static recache()
Definition SiteStats.php:43
static users()
static int[] $pageCount
Definition SiteStats.php:37
static int $jobs
Definition SiteStats.php:34
static pages()
static unload()
Definition SiteStats.php:39
static doLoad( $db)
static numberingroup( $group)
Find the number of users in a given user group.
static activeUsers()
when a variable name is used in a it is silently declared as a new local masking the global
Definition design.txt:95
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
the array() calling protocol came about after MediaWiki 1.4rc1.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist & $tables
Definition hooks.txt:1028
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist 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:1096
processing should stop and the error should be shown to the user * false
Definition hooks.txt:189
returning false will NOT prevent logging $e
Definition hooks.txt:2110
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:37
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:34
$cache
Definition mcc.php:33
MediaWiki has optional support for a high distributed memory object caching system For general information on but for a larger site with heavy load
Definition memcached.txt:6
const DB_REPLICA
Definition defines.php:22
const DB_MASTER
Definition defines.php:23