[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/specials/ -> SpecialStatistics.php (source)

   1  <?php
   2  /**
   3   * Implements Special:Statistics
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @file
  21   * @ingroup SpecialPage
  22   */
  23  
  24  /**
  25   * Special page lists various statistics, including the contents of
  26   * `site_stats`, plus page view details if enabled
  27   *
  28   * @ingroup SpecialPage
  29   */
  30  class SpecialStatistics extends SpecialPage {
  31      private $views, $edits, $good, $images, $total, $users,
  32          $activeUsers = 0;
  33  
  34  	public function __construct() {
  35          parent::__construct( 'Statistics' );
  36      }
  37  
  38  	public function execute( $par ) {
  39          global $wgMemc;
  40  
  41          $disableCounters = $this->getConfig()->get( 'DisableCounters' );
  42          $miserMode = $this->getConfig()->get( 'MiserMode' );
  43  
  44          $this->setHeaders();
  45          $this->getOutput()->addModuleStyles( 'mediawiki.special' );
  46  
  47          $this->views = SiteStats::views();
  48          $this->edits = SiteStats::edits();
  49          $this->good = SiteStats::articles();
  50          $this->images = SiteStats::images();
  51          $this->total = SiteStats::pages();
  52          $this->users = SiteStats::users();
  53          $this->activeUsers = SiteStats::activeUsers();
  54          $this->hook = '';
  55  
  56          # Staticic - views
  57          $viewsStats = '';
  58          if ( !$disableCounters ) {
  59              $viewsStats = $this->getViewsStats();
  60          }
  61  
  62          # Set active user count
  63          if ( !$miserMode ) {
  64              $key = wfMemcKey( 'sitestats', 'activeusers-updated' );
  65              // Re-calculate the count if the last tally is old...
  66              if ( !$wgMemc->get( $key ) ) {
  67                  $dbw = wfGetDB( DB_MASTER );
  68                  SiteStatsUpdate::cacheUpdate( $dbw );
  69                  $wgMemc->set( $key, '1', 24 * 3600 ); // don't update for 1 day
  70              }
  71          }
  72  
  73          $text = Xml::openElement( 'table', array( 'class' => 'wikitable mw-statistics-table' ) );
  74  
  75          # Statistic - pages
  76          $text .= $this->getPageStats();
  77  
  78          # Statistic - edits
  79          $text .= $this->getEditStats();
  80  
  81          # Statistic - users
  82          $text .= $this->getUserStats();
  83  
  84          # Statistic - usergroups
  85          $text .= $this->getGroupStats();
  86          $text .= $viewsStats;
  87  
  88          # Statistic - popular pages
  89          if ( !$disableCounters && !$miserMode ) {
  90              $text .= $this->getMostViewedPages();
  91          }
  92  
  93          # Statistic - other
  94          $extraStats = array();
  95          if ( wfRunHooks( 'SpecialStatsAddExtra', array( &$extraStats ) ) ) {
  96              $text .= $this->getOtherStats( $extraStats );
  97          }
  98  
  99          $text .= Xml::closeElement( 'table' );
 100  
 101          # Customizable footer
 102          $footer = $this->msg( 'statistics-footer' );
 103          if ( !$footer->isBlank() ) {
 104              $text .= "\n" . $footer->parse();
 105          }
 106  
 107          $this->getOutput()->addHTML( $text );
 108      }
 109  
 110      /**
 111       * Format a row
 112       * @param string $text Description of the row
 113       * @param float $number A statistical number
 114       * @param array $trExtraParams Params to table row, see Html::elememt
 115       * @param string $descMsg Message key
 116       * @param array|string $descMsgParam Message parameters
 117       * @return string Table row in HTML format
 118       */
 119  	private function formatRow( $text, $number, $trExtraParams = array(),
 120          $descMsg = '', $descMsgParam = ''
 121      ) {
 122          if ( $descMsg ) {
 123              $msg = $this->msg( $descMsg, $descMsgParam );
 124              if ( $msg->exists() ) {
 125                  $descriptionText = $this->msg( 'parentheses' )->rawParams( $msg->parse() )->escaped();
 126                  $text .= "<br />" . Xml::element( 'small', array( 'class' => 'mw-statistic-desc' ),
 127                      " $descriptionText" );
 128              }
 129          }
 130  
 131          return Html::rawElement( 'tr', $trExtraParams,
 132              Html::rawElement( 'td', array(), $text ) .
 133              Html::rawElement( 'td', array( 'class' => 'mw-statistics-numbers' ), $number )
 134          );
 135      }
 136  
 137      /**
 138       * Each of these methods is pretty self-explanatory, get a particular
 139       * row for the table of statistics
 140       * @return string
 141       */
 142  	private function getPageStats() {
 143          return Xml::openElement( 'tr' ) .
 144              Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-pages' )->parse() ) .
 145              Xml::closeElement( 'tr' ) .
 146                  $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'Allpages' ),
 147                      $this->msg( 'statistics-articles' )->parse() ),
 148                      $this->getLanguage()->formatNum( $this->good ),
 149                      array( 'class' => 'mw-statistics-articles' ) ) .
 150                  $this->formatRow( $this->msg( 'statistics-pages' )->parse(),
 151                      $this->getLanguage()->formatNum( $this->total ),
 152                      array( 'class' => 'mw-statistics-pages' ),
 153                      'statistics-pages-desc' ) .
 154                  $this->formatRow( Linker::linkKnown( SpecialPage::getTitleFor( 'MediaStatistics' ),
 155                      $this->msg( 'statistics-files' )->parse() ),
 156                      $this->getLanguage()->formatNum( $this->images ),
 157                      array( 'class' => 'mw-statistics-files' ) );
 158      }
 159  
 160  	private function getEditStats() {
 161          return Xml::openElement( 'tr' ) .
 162              Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-edits' )->parse() ) .
 163              Xml::closeElement( 'tr' ) .
 164              $this->formatRow( $this->msg( 'statistics-edits' )->parse(),
 165                  $this->getLanguage()->formatNum( $this->edits ),
 166                  array( 'class' => 'mw-statistics-edits' )
 167              ) .
 168              $this->formatRow( $this->msg( 'statistics-edits-average' )->parse(),
 169                  $this->getLanguage()
 170                      ->formatNum( sprintf( '%.2f', $this->total ? $this->edits / $this->total : 0 ) ),
 171                  array( 'class' => 'mw-statistics-edits-average' )
 172              );
 173      }
 174  
 175  	private function getUserStats() {
 176          return Xml::openElement( 'tr' ) .
 177              Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-users' )->parse() ) .
 178              Xml::closeElement( 'tr' ) .
 179              $this->formatRow( $this->msg( 'statistics-users' )->parse(),
 180                  $this->getLanguage()->formatNum( $this->users ),
 181                  array( 'class' => 'mw-statistics-users' )
 182              ) .
 183              $this->formatRow( $this->msg( 'statistics-users-active' )->parse() . ' ' .
 184                  Linker::linkKnown(
 185                      SpecialPage::getTitleFor( 'Activeusers' ),
 186                      $this->msg( 'listgrouprights-members' )->escaped()
 187                  ),
 188                  $this->getLanguage()->formatNum( $this->activeUsers ),
 189                  array( 'class' => 'mw-statistics-users-active' ),
 190                  'statistics-users-active-desc',
 191                  $this->getLanguage()->formatNum( $this->getConfig()->get( 'ActiveUserDays' ) )
 192              );
 193      }
 194  
 195  	private function getGroupStats() {
 196          $text = '';
 197          foreach ( $this->getConfig()->get( 'GroupPermissions' ) as $group => $permissions ) {
 198              # Skip generic * and implicit groups
 199              if ( in_array( $group, $this->getConfig()->get( 'ImplicitGroups' ) ) || $group == '*' ) {
 200                  continue;
 201              }
 202              $groupname = htmlspecialchars( $group );
 203              $msg = $this->msg( 'group-' . $groupname );
 204              if ( $msg->isBlank() ) {
 205                  $groupnameLocalized = $groupname;
 206              } else {
 207                  $groupnameLocalized = $msg->text();
 208              }
 209              $msg = $this->msg( 'grouppage-' . $groupname )->inContentLanguage();
 210              if ( $msg->isBlank() ) {
 211                  $grouppageLocalized = MWNamespace::getCanonicalName( NS_PROJECT ) . ':' . $groupname;
 212              } else {
 213                  $grouppageLocalized = $msg->text();
 214              }
 215              $linkTarget = Title::newFromText( $grouppageLocalized );
 216              $grouppage = Linker::link(
 217                  $linkTarget,
 218                  htmlspecialchars( $groupnameLocalized )
 219              );
 220              $grouplink = Linker::linkKnown(
 221                  SpecialPage::getTitleFor( 'Listusers' ),
 222                  $this->msg( 'listgrouprights-members' )->escaped(),
 223                  array(),
 224                  array( 'group' => $group )
 225              );
 226              # Add a class when a usergroup contains no members to allow hiding these rows
 227              $classZero = '';
 228              $countUsers = SiteStats::numberingroup( $groupname );
 229              if ( $countUsers == 0 ) {
 230                  $classZero = ' statistics-group-zero';
 231              }
 232              $text .= $this->formatRow( $grouppage . ' ' . $grouplink,
 233                  $this->getLanguage()->formatNum( $countUsers ),
 234                  array( 'class' => 'statistics-group-' . Sanitizer::escapeClass( $group ) . $classZero ) );
 235          }
 236  
 237          return $text;
 238      }
 239  
 240  	private function getViewsStats() {
 241          return Xml::openElement( 'tr' ) .
 242              Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( 'statistics-header-views' )->parse() ) .
 243              Xml::closeElement( 'tr' ) .
 244                  $this->formatRow( $this->msg( 'statistics-views-total' )->parse(),
 245                      $this->getLanguage()->formatNum( $this->views ),
 246                          array( 'class' => 'mw-statistics-views-total' ), 'statistics-views-total-desc' ) .
 247                  $this->formatRow( $this->msg( 'statistics-views-peredit' )->parse(),
 248                      $this->getLanguage()->formatNum( sprintf( '%.2f', $this->edits ?
 249                          $this->views / $this->edits : 0 ) ),
 250                          array( 'class' => 'mw-statistics-views-peredit' ) );
 251      }
 252  
 253  	private function getMostViewedPages() {
 254          $text = '';
 255          $dbr = wfGetDB( DB_SLAVE );
 256          $res = $dbr->select(
 257              'page',
 258              array(
 259                  'page_namespace',
 260                  'page_title',
 261                  'page_counter',
 262              ),
 263              array(
 264                  'page_is_redirect' => 0,
 265                  'page_counter > 0',
 266              ),
 267              __METHOD__,
 268              array(
 269                  'ORDER BY' => 'page_counter DESC',
 270                  'LIMIT' => 10,
 271              )
 272          );
 273  
 274          if ( $res->numRows() > 0 ) {
 275              $text .= Xml::openElement( 'tr' );
 276              $text .= Xml::tags(
 277                  'th',
 278                  array( 'colspan' => '2' ),
 279                  $this->msg( 'statistics-mostpopular' )->parse()
 280              );
 281              $text .= Xml::closeElement( 'tr' );
 282  
 283              foreach ( $res as $row ) {
 284                  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
 285  
 286                  if ( $title instanceof Title ) {
 287                      $text .= $this->formatRow( Linker::link( $title ),
 288                          $this->getLanguage()->formatNum( $row->page_counter ) );
 289                  }
 290              }
 291              $res->free();
 292          }
 293  
 294          return $text;
 295      }
 296  
 297      /**
 298       * Conversion of external statistics into an internal representation
 299       * Following a ([<header-message>][<item-message>] = number) pattern
 300       *
 301       * @param array $stats
 302       * @return string
 303       */
 304  	private function getOtherStats( array $stats ) {
 305          $return = '';
 306  
 307          foreach ( $stats as $header => $items ) {
 308              // Identify the structure used
 309              if ( is_array( $items ) ) {
 310  
 311                  // Ignore headers that are recursively set as legacy header
 312                  if ( $header !== 'statistics-header-hooks' ) {
 313                      $return .= $this->formatRowHeader( $header );
 314                  }
 315  
 316                  // Collect all items that belong to the same header
 317                  foreach ( $items as $key => $value ) {
 318                      $name = $this->msg( $key )->parse();
 319                      $number = htmlspecialchars( $value );
 320  
 321                      $return .= $this->formatRow(
 322                          $name,
 323                          $this->getLanguage()->formatNum( $number ),
 324                          array( 'class' => 'mw-statistics-hook', 'id' => 'mw-' . $key )
 325                      );
 326                  }
 327              } else {
 328                  // Create the legacy header only once
 329                  if ( $return === '' ) {
 330                      $return .= $this->formatRowHeader( 'statistics-header-hooks' );
 331                  }
 332  
 333                  // Recursively remap the legacy structure
 334                  $return .= $this->getOtherStats( array( 'statistics-header-hooks' =>
 335                      array( $header => $items ) ) );
 336              }
 337          }
 338  
 339          return $return;
 340      }
 341  
 342      /**
 343       * Format row header
 344       *
 345       * @param string $header
 346       * @return string
 347       */
 348  	private function formatRowHeader( $header ) {
 349          return Xml::openElement( 'tr' ) .
 350              Xml::tags( 'th', array( 'colspan' => '2' ), $this->msg( $header )->parse() ) .
 351              Xml::closeElement( 'tr' );
 352      }
 353  
 354  	protected function getGroupName() {
 355          return 'wiki';
 356      }
 357  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1