]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/specials/SpecialStatistics.php
MediaWiki 1.16.1-scripts
[autoinstallsdev/mediawiki.git] / includes / specials / SpecialStatistics.php
1 <?php
2
3 /**
4  * Special page lists various statistics, including the contents of
5  * `site_stats`, plus page view details if enabled
6  *
7  * @file
8  * @ingroup SpecialPage
9  */
10
11 /**
12  * Show the special page
13  *
14  * @param mixed $par (not used)
15  */
16 class SpecialStatistics extends SpecialPage {
17         
18         private $views, $edits, $good, $images, $total, $users,
19                         $activeUsers, $admins, $numJobs = 0;
20         
21         public function __construct() {
22                 parent::__construct( 'Statistics' );
23         }
24         
25         public function execute( $par ) {
26                 global $wgOut, $wgRequest, $wgMessageCache, $wgMemc;
27                 global $wgDisableCounters, $wgMiserMode;
28                 $wgMessageCache->loadAllMessages();
29                 
30                 $this->setHeaders();
31         
32                 $this->views = SiteStats::views();
33                 $this->edits = SiteStats::edits();
34                 $this->good = SiteStats::articles();
35                 $this->images = SiteStats::images();
36                 $this->total = SiteStats::pages();
37                 $this->users = SiteStats::users();
38                 $this->activeUsers = SiteStats::activeUsers();
39                 $this->admins = SiteStats::numberingroup('sysop');
40                 $this->numJobs = SiteStats::jobs();
41                 $this->hook = '';
42         
43                 # Staticic - views
44                 $viewsStats = '';
45                 if( !$wgDisableCounters ) {
46                         $viewsStats = $this->getViewsStats();
47                 }
48                 
49                 # Set active user count
50                 if( !$wgMiserMode ) {
51                         $key = wfMemcKey( 'sitestats', 'activeusers-updated' );
52                         // Re-calculate the count if the last tally is old...
53                         if( !$wgMemc->get($key) ) {
54                                 $dbw = wfGetDB( DB_MASTER );
55                                 SiteStatsUpdate::cacheUpdate( $dbw );
56                                 $wgMemc->set( $key, '1', 24*3600 ); // don't update for 1 day
57                         }
58                 }
59         
60                 # Do raw output
61                 if( $wgRequest->getVal( 'action' ) == 'raw' ) {
62                         $this->doRawOutput();
63                 }
64
65                 $text = Xml::openElement( 'table', array( 'class' => 'wikitable mw-statistics-table' ) );
66
67                 # Statistic - pages
68                 $text .= $this->getPageStats();
69
70                 # Statistic - edits
71                 $text .= $this->getEditStats();
72
73                 # Statistic - users
74                 $text .= $this->getUserStats();
75
76                 # Statistic - usergroups
77                 $text .= $this->getGroupStats();
78                 $text .= $viewsStats;
79
80                 # Statistic - popular pages
81                 if( !$wgDisableCounters && !$wgMiserMode ) {
82                         $text .= $this->getMostViewedPages();
83                 }
84                 
85                 # Statistic - other
86                 $extraStats = array();
87                 if( wfRunHooks( 'SpecialStatsAddExtra', array( &$extraStats ) ) ) {
88                         $text .= $this->getOtherStats( $extraStats );
89                 }
90
91                 $text .= Xml::closeElement( 'table' );
92
93                 # Customizable footer
94                 $footer = wfMsgExt( 'statistics-footer', array('parseinline') );
95                 if( !wfEmptyMsg( 'statistics-footer', $footer ) && $footer != '' ) {
96                         $text .= "\n" . $footer;
97                 }
98
99                 $wgOut->addHTML( $text );
100         }
101
102         /**
103          * Format a row
104          * @param string $text description of the row
105          * @param float $number a number
106          * @param array $trExtraParams
107          * @param string $descMsg
108          * @param string $descMsgParam
109          * @return string table row in HTML format
110          */
111         private function formatRow( $text, $number, $trExtraParams = array(), $descMsg = '', $descMsgParam = '' ) {
112                 global $wgStylePath;
113                 if( $descMsg ) {
114                         $descriptionText = wfMsgExt( $descMsg, array( 'parseinline' ), $descMsgParam );
115                         if ( !wfEmptyMsg( $descMsg, $descriptionText ) ) {
116                                 $descriptionText = " ($descriptionText)";
117                                 $text .= "<br />" . Xml::element( 'small', array( 'class' => 'mw-statistic-desc'), 
118                                         $descriptionText );
119                         }
120                 }
121                 return Xml::openElement( 'tr', $trExtraParams ) .
122                         Xml::openElement( 'td' ) . $text . Xml::closeElement( 'td' ) .
123                         Xml::openElement( 'td', array( 'class' => 'mw-statistics-numbers' ) ) . $number . Xml::closeElement( 'td' ) .
124                         Xml::closeElement( 'tr' );
125         }
126         
127         /**
128          * Each of these methods is pretty self-explanatory, get a particular
129          * row for the table of statistics
130          * @return string
131          */
132         private function getPageStats() {
133                 global $wgLang;
134                 return Xml::openElement( 'tr' ) .
135                         Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-pages', array( 'parseinline' ) ) ) .
136                         Xml::closeElement( 'tr' ) .
137                                 $this->formatRow( wfMsgExt( 'statistics-articles', array( 'parseinline' ) ),
138                                                 $wgLang->formatNum( $this->good ),
139                                                 array( 'class' => 'mw-statistics-articles' ) ) .
140                                 $this->formatRow( wfMsgExt( 'statistics-pages', array( 'parseinline' ) ),
141                                                 $wgLang->formatNum( $this->total ),
142                                                 array( 'class' => 'mw-statistics-pages' ),
143                                                 'statistics-pages-desc' ) .
144                                 $this->formatRow( wfMsgExt( 'statistics-files', array( 'parseinline' ) ),
145                                                 $wgLang->formatNum( $this->images ),
146                                                 array( 'class' => 'mw-statistics-files' ) );
147         }
148         private function getEditStats() {
149                 global $wgLang;
150                 return Xml::openElement( 'tr' ) .
151                         Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-edits', array( 'parseinline' ) ) ) .
152                         Xml::closeElement( 'tr' ) .
153                                 $this->formatRow( wfMsgExt( 'statistics-edits', array( 'parseinline' ) ),
154                                                 $wgLang->formatNum( $this->edits ),
155                                                 array( 'class' => 'mw-statistics-edits' ) ) .
156                                 $this->formatRow( wfMsgExt( 'statistics-edits-average', array( 'parseinline' ) ),
157                                                 $wgLang->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ),
158                                                 array( 'class' => 'mw-statistics-edits-average' ) ) .
159                                 $this->formatRow( wfMsgExt( 'statistics-jobqueue', array( 'parseinline' ) ),
160                                                 $wgLang->formatNum( $this->numJobs ),
161                                                 array( 'class' => 'mw-statistics-jobqueue' ) );
162         }
163         private function getUserStats() {
164                 global $wgLang, $wgUser, $wgRCMaxAge;
165                 $sk = $wgUser->getSkin();
166                 return Xml::openElement( 'tr' ) .
167                         Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-users', array( 'parseinline' ) ) ) .
168                         Xml::closeElement( 'tr' ) .
169                                 $this->formatRow( wfMsgExt( 'statistics-users', array( 'parseinline' ) ),
170                                                 $wgLang->formatNum( $this->users ),
171                                                 array( 'class' => 'mw-statistics-users' ) ) .
172                                 $this->formatRow( wfMsgExt( 'statistics-users-active', array( 'parseinline' ) ) . ' ' .
173                                                         $sk->link(
174                                                                 SpecialPage::getTitleFor( 'Activeusers' ),
175                                                                 wfMsgHtml( 'listgrouprights-members' ),
176                                                                 array(),
177                                                                 array(),
178                                                                 'known'
179                                                         ),
180                                                 $wgLang->formatNum( $this->activeUsers ),
181                                                 array( 'class' => 'mw-statistics-users-active' ),
182                                                 'statistics-users-active-desc',
183                                                 $wgLang->formatNum( ceil( $wgRCMaxAge / ( 3600 * 24 ) ) ) );
184         }
185         private function getGroupStats() {
186                 global $wgGroupPermissions, $wgImplicitGroups, $wgLang, $wgUser;
187                 $sk = $wgUser->getSkin();
188                 $text = '';
189                 foreach( $wgGroupPermissions as $group => $permissions ) {
190                         # Skip generic * and implicit groups
191                         if ( in_array( $group, $wgImplicitGroups ) || $group == '*' ) {
192                                 continue;
193                         }
194                         $groupname = htmlspecialchars( $group );
195                         $msg = wfMsg( 'group-' . $groupname );
196                         if ( wfEmptyMsg( 'group-' . $groupname, $msg ) || $msg == '' ) {
197                                 $groupnameLocalized = $groupname;
198                         } else {
199                                 $groupnameLocalized = $msg;
200                         }
201                         $msg = wfMsgForContent( 'grouppage-' . $groupname );
202                         if ( wfEmptyMsg( 'grouppage-' . $groupname, $msg ) || $msg == '' ) {
203                                 $grouppageLocalized = MWNamespace::getCanonicalName( NS_PROJECT ) . ':' . $groupname;
204                         } else {
205                                 $grouppageLocalized = $msg;
206                         }
207                         $linkTarget = Title::newFromText( $grouppageLocalized );
208                         $grouppage = $sk->link(
209                                 $linkTarget,
210                                 htmlspecialchars( $groupnameLocalized )
211                         );
212                         $grouplink = $sk->link(
213                                 SpecialPage::getTitleFor( 'Listusers' ),
214                                 wfMsgHtml( 'listgrouprights-members' ),
215                                 array(),
216                                 array( 'group' => $group ),
217                                 'known'
218                         );
219                         # Add a class when a usergroup contains no members to allow hiding these rows
220                         $classZero = '';
221                         $countUsers = SiteStats::numberingroup( $groupname );
222                         if( $countUsers == 0 ) {
223                                 $classZero = ' statistics-group-zero';
224                         }
225                         $text .= $this->formatRow( $grouppage . ' ' . $grouplink,
226                                 $wgLang->formatNum( $countUsers ),
227                                 array( 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) . $classZero )  );
228                 }
229                 return $text;
230         }
231         private function getViewsStats() {
232                 global $wgLang;
233                 return Xml::openElement( 'tr' ) .
234                         Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-views', array( 'parseinline' ) ) ) .
235                         Xml::closeElement( 'tr' ) .
236                                 $this->formatRow( wfMsgExt( 'statistics-views-total', array( 'parseinline' ) ),
237                                         $wgLang->formatNum( $this->views ),
238                                                 array ( 'class' => 'mw-statistics-views-total' ) ) .
239                                 $this->formatRow( wfMsgExt( 'statistics-views-peredit', array( 'parseinline' ) ),
240                                         $wgLang->formatNum( sprintf( '%.2f', $this->edits ? 
241                                                 $this->views / $this->edits : 0 ) ),
242                                                 array ( 'class' => 'mw-statistics-views-peredit' ) );
243         }
244         private function getMostViewedPages() {
245                 global $wgLang, $wgUser;
246                 $text = '';
247                 $dbr = wfGetDB( DB_SLAVE );
248                 $sk = $wgUser->getSkin();
249                 $res = $dbr->select(
250                                 'page',
251                                 array(
252                                         'page_namespace',
253                                         'page_title',
254                                         'page_counter',
255                                 ),
256                                 array(
257                                         'page_is_redirect' => 0,
258                                         'page_counter > 0',
259                                 ),
260                                 __METHOD__,
261                                 array(
262                                         'ORDER BY' => 'page_counter DESC',
263                                         'LIMIT' => 10,
264                                 )
265                         );
266                         if( $res->numRows() > 0 ) {
267                                 $text .= Xml::openElement( 'tr' );
268                                 $text .= Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-mostpopular', array( 'parseinline' ) ) );
269                                 $text .= Xml::closeElement( 'tr' );
270                                 while( $row = $res->fetchObject() ) {
271                                         $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
272                                         if( $title instanceof Title ) {
273                                                 $text .= $this->formatRow( $sk->link( $title ),
274                                                                 $wgLang->formatNum( $row->page_counter ) );
275         
276                                         }
277                                 }
278                                 $res->free();
279                         }
280                 return $text;
281         }
282         
283         private function getOtherStats( $stats ) {
284                 global $wgLang;
285
286                 if ( !count( $stats ) )
287                         return '';
288
289                 $return = Xml::openElement( 'tr' ) .
290                         Xml::tags( 'th', array( 'colspan' => '2' ), wfMsgExt( 'statistics-header-hooks', array( 'parseinline' ) ) ) .
291                         Xml::closeElement( 'tr' );
292                         
293                 foreach( $stats as $name => $number ) {
294                         $name = htmlspecialchars( $name );
295                         $number = htmlspecialchars( $number );
296                         
297                         $return .= $this->formatRow( $name, $wgLang->formatNum( $number ), array( 'class' => 'mw-statistics-hook' ) );
298                 }
299                 
300                 return $return;
301         }
302         
303         /**
304          * Do the action=raw output for this page. Legacy, but we support
305          * it for backwards compatibility
306          * http://lists.wikimedia.org/pipermail/wikitech-l/2008-August/039202.html
307          */
308         private function doRawOutput() {
309                 global $wgOut;
310                 $wgOut->disable();
311                 header( 'Pragma: nocache' );
312                 echo "total=" . $this->total . ";good=" . $this->good . ";views=" . 
313                                 $this->views . ";edits=" . $this->edits . ";users=" . $this->users . ";";
314                 echo "activeusers=" . $this->activeUsers . ";admins=" . $this->admins . 
315                                 ";images=" . $this->images . ";jobs=" . $this->numJobs . "\n";
316                 return;
317         }
318 }