MediaWiki
REL1_22
|
00001 <?php 00030 class SpecialStatistics extends SpecialPage { 00031 00032 private $views, $edits, $good, $images, $total, $users, 00033 $activeUsers = 0; 00034 00035 public function __construct() { 00036 parent::__construct( 'Statistics' ); 00037 } 00038 00039 public function execute( $par ) { 00040 global $wgMemc, $wgDisableCounters, $wgMiserMode; 00041 00042 $this->setHeaders(); 00043 $this->getOutput()->addModuleStyles( 'mediawiki.special' ); 00044 00045 $this->views = SiteStats::views(); 00046 $this->edits = SiteStats::edits(); 00047 $this->good = SiteStats::articles(); 00048 $this->images = SiteStats::images(); 00049 $this->total = SiteStats::pages(); 00050 $this->users = SiteStats::users(); 00051 $this->activeUsers = SiteStats::activeUsers(); 00052 $this->hook = ''; 00053 00054 # Staticic - views 00055 $viewsStats = ''; 00056 if ( !$wgDisableCounters ) { 00057 $viewsStats = $this->getViewsStats(); 00058 } 00059 00060 # Set active user count 00061 if ( !$wgMiserMode ) { 00062 $key = wfMemcKey( 'sitestats', 'activeusers-updated' ); 00063 // Re-calculate the count if the last tally is old... 00064 if ( !$wgMemc->get( $key ) ) { 00065 $dbw = wfGetDB( DB_MASTER ); 00066 SiteStatsUpdate::cacheUpdate( $dbw ); 00067 $wgMemc->set( $key, '1', 24 * 3600 ); // don't update for 1 day 00068 } 00069 } 00070 00071 $text = Xml::openElement( 'table', array( 'class' => 'wikitable mw-statistics-table' ) ); 00072 00073 # Statistic - pages 00074 $text .= $this->getPageStats(); 00075 00076 # Statistic - edits 00077 $text .= $this->getEditStats(); 00078 00079 # Statistic - users 00080 $text .= $this->getUserStats(); 00081 00082 # Statistic - usergroups 00083 $text .= $this->getGroupStats(); 00084 $text .= $viewsStats; 00085 00086 # Statistic - popular pages 00087 if ( !$wgDisableCounters && !$wgMiserMode ) { 00088 $text .= $this->getMostViewedPages(); 00089 } 00090 00091 # Statistic - other 00092 $extraStats = array(); 00093 if ( wfRunHooks( 'SpecialStatsAddExtra', array( &$extraStats ) ) ) { 00094 $text .= $this->getOtherStats( $extraStats ); 00095 } 00096 00097 $text .= Xml::closeElement( 'table' ); 00098 00099 # Customizable footer 00100 $footer = $this->msg( 'statistics-footer' ); 00101 if ( !$footer->isBlank() ) { 00102 $text .= "\n" . $footer->parse(); 00103 } 00104 00105 $this->getOutput()->addHTML( $text ); 00106 } 00107 00117 private function formatRow( $text, $number, $trExtraParams = array(), $descMsg = '', $descMsgParam = '' ) { 00118 if ( $descMsg ) { 00119 $msg = $this->msg( $descMsg, $descMsgParam ); 00120 if ( $msg->exists() ) { 00121 $descriptionText = $this->msg( 'parentheses' )->rawParams( $msg->parse() )->escaped(); 00122 $text .= "<br />" . Xml::element( 'small', array( 'class' => 'mw-statistic-desc' ), 00123 " $descriptionText" ); 00124 } 00125 } 00126 return Html::rawElement( 'tr', $trExtraParams, 00127 Html::rawElement( 'td', array(), $text ) . 00128 Html::rawElement( 'td', array( 'class' => 'mw-statistics-numbers' ), $number ) 00129 ); 00130 } 00131 00137 private function getPageStats() { 00138 return Xml::openElement( 'tr' ) . 00139 Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-pages' )->parse() ) . 00140 Xml::closeElement( 'tr' ) . 00141 $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Allpages' ), 00142 $this->msg( 'statistics-articles' )->parse() ), 00143 $this->getLanguage()->formatNum( $this->good ), 00144 array( 'class' => 'mw-statistics-articles' ) ) . 00145 $this->formatRow( $this->msg( 'statistics-pages' )->parse(), 00146 $this->getLanguage()->formatNum( $this->total ), 00147 array( 'class' => 'mw-statistics-pages' ), 00148 'statistics-pages-desc' ) . 00149 $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Listfiles' ), 00150 $this->msg( 'statistics-files' )->parse() ), 00151 $this->getLanguage()->formatNum( $this->images ), 00152 array( 'class' => 'mw-statistics-files' ) ); 00153 } 00154 private function getEditStats() { 00155 return Xml::openElement( 'tr' ) . 00156 Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-edits' )->parse() ) . 00157 Xml::closeElement( 'tr' ) . 00158 $this->formatRow( $this->msg( 'statistics-edits' )->parse(), 00159 $this->getLanguage()->formatNum( $this->edits ), 00160 array( 'class' => 'mw-statistics-edits' ) ) . 00161 $this->formatRow( $this->msg( 'statistics-edits-average' )->parse(), 00162 $this->getLanguage()->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ), 00163 array( 'class' => 'mw-statistics-edits-average' ) ); 00164 } 00165 00166 private function getUserStats() { 00167 global $wgActiveUserDays; 00168 return Xml::openElement( 'tr' ) . 00169 Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-users' )->parse() ) . 00170 Xml::closeElement( 'tr' ) . 00171 $this->formatRow( $this->msg( 'statistics-users' )->parse(), 00172 $this->getLanguage()->formatNum( $this->users ), 00173 array( 'class' => 'mw-statistics-users' ) ) . 00174 $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' . 00175 Linker::linkKnown( 00176 SpecialPage::getTitleFor( 'Activeusers' ), 00177 $this->msg( 'listgrouprights-members' )->escaped() 00178 ), 00179 $this->getLanguage()->formatNum( $this->activeUsers ), 00180 array( 'class' => 'mw-statistics-users-active' ), 00181 'statistics-users-active-desc', 00182 $this->getLanguage()->formatNum( $wgActiveUserDays ) ); 00183 } 00184 00185 private function getGroupStats() { 00186 global $wgGroupPermissions, $wgImplicitGroups; 00187 $text = ''; 00188 foreach ( $wgGroupPermissions as $group => $permissions ) { 00189 # Skip generic * and implicit groups 00190 if ( in_array( $group, $wgImplicitGroups ) || $group == '*' ) { 00191 continue; 00192 } 00193 $groupname = htmlspecialchars( $group ); 00194 $msg = $this->msg( 'group-' . $groupname ); 00195 if ( $msg->isBlank() ) { 00196 $groupnameLocalized = $groupname; 00197 } else { 00198 $groupnameLocalized = $msg->text(); 00199 } 00200 $msg = $this->msg( 'grouppage-' . $groupname )->inContentLanguage(); 00201 if ( $msg->isBlank() ) { 00202 $grouppageLocalized = MWNamespace::getCanonicalName( NS_PROJECT ) . ':' . $groupname; 00203 } else { 00204 $grouppageLocalized = $msg->text(); 00205 } 00206 $linkTarget = Title::newFromText( $grouppageLocalized ); 00207 $grouppage = Linker::link( 00208 $linkTarget, 00209 htmlspecialchars( $groupnameLocalized ) 00210 ); 00211 $grouplink = Linker::linkKnown( 00212 SpecialPage::getTitleFor( 'Listusers' ), 00213 $this->msg( 'listgrouprights-members' )->escaped(), 00214 array(), 00215 array( 'group' => $group ) 00216 ); 00217 # Add a class when a usergroup contains no members to allow hiding these rows 00218 $classZero = ''; 00219 $countUsers = SiteStats::numberingroup( $groupname ); 00220 if ( $countUsers == 0 ) { 00221 $classZero = ' statistics-group-zero'; 00222 } 00223 $text .= $this->formatRow( $grouppage . ' ' . $grouplink, 00224 $this->getLanguage()->formatNum( $countUsers ), 00225 array( 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) . $classZero ) ); 00226 } 00227 return $text; 00228 } 00229 00230 private function getViewsStats() { 00231 return Xml::openElement( 'tr' ) . 00232 Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-views' )->parse() ) . 00233 Xml::closeElement( 'tr' ) . 00234 $this->formatRow( $this->msg( 'statistics-views-total' )->parse(), 00235 $this->getLanguage()->formatNum( $this->views ), 00236 array( 'class' => 'mw-statistics-views-total' ), 'statistics-views-total-desc' ) . 00237 $this->formatRow( $this->msg( 'statistics-views-peredit' )->parse(), 00238 $this->getLanguage()->formatNum( sprintf( '%.2f', $this->edits ? 00239 $this->views / $this->edits : 0 ) ), 00240 array( 'class' => 'mw-statistics-views-peredit' ) ); 00241 } 00242 00243 private function getMostViewedPages() { 00244 $text = ''; 00245 $dbr = wfGetDB( DB_SLAVE ); 00246 $res = $dbr->select( 00247 'page', 00248 array( 00249 'page_namespace', 00250 'page_title', 00251 'page_counter', 00252 ), 00253 array( 00254 'page_is_redirect' => 0, 00255 'page_counter > 0', 00256 ), 00257 __METHOD__, 00258 array( 00259 'ORDER BY' => 'page_counter DESC', 00260 'LIMIT' => 10, 00261 ) 00262 ); 00263 if ( $res->numRows() > 0 ) { 00264 $text .= Xml::openElement( 'tr' ); 00265 $text .= Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-mostpopular' )->parse() ); 00266 $text .= Xml::closeElement( 'tr' ); 00267 foreach ( $res as $row ) { 00268 $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title ); 00269 if ( $title instanceof Title ) { 00270 $text .= $this->formatRow( Linker::link( $title ), 00271 $this->getLanguage()->formatNum( $row->page_counter ) ); 00272 00273 } 00274 } 00275 $res->free(); 00276 } 00277 return $text; 00278 } 00279 00287 private function getOtherStats( array $stats ) { 00288 $return = ''; 00289 00290 foreach ( $stats as $header => $items ) { 00291 // Identify the structure used 00292 if ( is_array( $items ) ) { 00293 00294 // Ignore headers that are recursively set as legacy header 00295 if ( $header !== 'statistics-header-hooks' ) { 00296 $return .= $this->formatRowHeader( $header ); 00297 } 00298 00299 // Collect all items that belong to the same header 00300 foreach ( $items as $key => $value ) { 00301 $name = $this->msg( $key )->parse(); 00302 $number = htmlspecialchars( $value ); 00303 00304 $return .= $this->formatRow( $name, $this->getLanguage()->formatNum( $number ), array( 'class' => 'mw-statistics-hook', 'id' => 'mw-' . $key ) ); 00305 } 00306 } else { 00307 // Create the legacy header only once 00308 if ( $return === '' ) { 00309 $return .= $this->formatRowHeader( 'statistics-header-hooks' ); 00310 } 00311 00312 // Recursively remap the legacy structure 00313 $return .= $this->getOtherStats( array( 'statistics-header-hooks' => array( $header => $items ) ) ); 00314 } 00315 } 00316 00317 return $return; 00318 } 00319 00326 private function formatRowHeader( $header ) { 00327 return Xml::openElement( 'tr' ) . 00328 Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( $header )->parse() ) . 00329 Xml::closeElement( 'tr' ); 00330 } 00331 00332 protected function getGroupName() { 00333 return 'wiki'; 00334 } 00335 }