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