[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Implements Special:MediaStatistics
   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   * @author Brian Wolff
  23   */
  24  
  25  /**
  26   * @ingroup SpecialPage
  27   */
  28  class MediaStatisticsPage extends QueryPage {
  29      protected $totalCount = 0, $totalBytes = 0;
  30  
  31  	function __construct( $name = 'MediaStatistics' ) {
  32          parent::__construct( $name );
  33          // Generally speaking there is only a small number of file types,
  34          // so just show all of them.
  35          $this->limit = 5000;
  36          $this->shownavigation = false;
  37      }
  38  
  39  	function isExpensive() {
  40          return true;
  41      }
  42  
  43      /**
  44       * Query to do.
  45       *
  46       * This abuses the query cache table by storing mime types as "titles".
  47       *
  48       * This will store entries like [[Media:BITMAP;image/jpeg;200;20000]]
  49       * where the form is Media type;mime type;count;bytes.
  50       *
  51       * This relies on the behaviour that when value is tied, the order things
  52       * come out of querycache table is the order they went in. Which is hacky.
  53       * However, other special pages like Special:Deadendpages and
  54       * Special:BrokenRedirects also rely on this.
  55       */
  56  	public function getQueryInfo() {
  57          $dbr = wfGetDB( DB_SLAVE );
  58          $fakeTitle = $dbr->buildConcat( array(
  59              'img_media_type',
  60              $dbr->addQuotes( ';' ),
  61              'img_major_mime',
  62              $dbr->addQuotes( '/' ),
  63              'img_minor_mime',
  64              $dbr->addQuotes( ';' ),
  65              'COUNT(*)',
  66              $dbr->addQuotes( ';' ),
  67              'SUM( img_size )'
  68          ) );
  69          return array(
  70              'tables' => array( 'image' ),
  71              'fields' => array(
  72                  'title' => $fakeTitle,
  73                  'namespace' => NS_MEDIA, /* needs to be something */
  74                  'value' => '1'
  75              ),
  76              'options' => array(
  77                  'GROUP BY' => array(
  78                      'img_media_type',
  79                      'img_major_mime',
  80                      'img_minor_mime',
  81                  )
  82              )
  83          );
  84      }
  85  
  86      /**
  87       * How to sort the results
  88       *
  89       * It's important that img_media_type come first, otherwise the
  90       * tables will be fragmented.
  91       * @return Array Fields to sort by
  92       */
  93  	function getOrderFields() {
  94          return array( 'img_media_type', 'count(*)', 'img_major_mime', 'img_minor_mime' );
  95      }
  96  
  97      /**
  98       * Output the results of the query.
  99       *
 100       * @param $out OutputPage
 101       * @param $skin Skin (deprecated presumably)
 102       * @param $dbr DatabaseBase
 103       * @param $res ResultWrapper Results from query
 104       * @param $num integer Number of results
 105       * @param $offset integer Paging offset (Should always be 0 in our case)
 106       */
 107  	protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
 108          $prevMediaType = null;
 109          foreach ( $res as $row ) {
 110              list( $mediaType, $mime, $totalCount, $totalBytes ) = $this->splitFakeTitle( $row->title );
 111              if ( $prevMediaType !== $mediaType ) {
 112                  if ( $prevMediaType !== null ) {
 113                      // We're not at beginning, so we have to
 114                      // close the previous table.
 115                      $this->outputTableEnd();
 116                  }
 117                  $this->outputMediaType( $mediaType );
 118                  $this->outputTableStart( $mediaType );
 119                  $prevMediaType = $mediaType;
 120              }
 121              $this->outputTableRow( $mime, intval( $totalCount ), intval( $totalBytes ) );
 122          }
 123          if ( $prevMediaType !== null ) {
 124              $this->outputTableEnd();
 125          }
 126      }
 127  
 128      /**
 129       * Output closing </table>
 130       */
 131  	protected function outputTableEnd() {
 132          $this->getOutput()->addHtml( Html::closeElement( 'table' ) );
 133      }
 134  
 135      /**
 136       * Output a row of the stats table
 137       *
 138       * @param $mime String mime type (e.g. image/jpeg)
 139       * @param $count integer Number of images of this type
 140       * @param $totalBytes integer Total space for images of this type
 141       */
 142  	protected function outputTableRow( $mime, $count, $bytes ) {
 143          $mimeSearch = SpecialPage::getTitleFor( 'MIMEsearch', $mime );
 144          $row = Html::rawElement(
 145              'td',
 146              array(),
 147              Linker::link( $mimeSearch, htmlspecialchars( $mime ) )
 148          );
 149          $row .= Html::element(
 150              'td',
 151              array(),
 152              $this->getExtensionList( $mime )
 153          );
 154          $row .= Html::rawElement(
 155              'td',
 156              array(),
 157              $this->msg( 'mediastatistics-nfiles' )
 158                  ->numParams( $count )
 159                  /** @todo Check to be sure this really should have number formatting */
 160                  ->numParams( $this->makePercentPretty( $count / $this->totalCount ) )
 161                  ->parse()
 162          );
 163          $row .= Html::rawElement(
 164              'td',
 165              // Make sure js sorts it in numeric order
 166              array( 'data-sort-value' =>  $bytes ),
 167              $this->msg( 'mediastatistics-nbytes' )
 168                  ->numParams( $bytes )
 169                  ->sizeParams( $bytes )
 170                  /** @todo Check to be sure this really should have number formatting */
 171                  ->numParams( $this->makePercentPretty( $bytes / $this->totalBytes ) )
 172                  ->parse()
 173          );
 174  
 175          $this->getOutput()->addHTML( Html::rawElement( 'tr', array(), $row ) );
 176      }
 177  
 178      /**
 179       * @param float $decimal A decimal percentage (ie for 12.3%, this would be 0.123)
 180       * @return String The percentage formatted so that 3 significant digits are shown.
 181       */
 182  	protected function makePercentPretty( $decimal ) {
 183          $decimal *= 100;
 184          // Always show three useful digits
 185          if ( $decimal == 0 ) {
 186              return '0';
 187          }
 188          $percent = sprintf( "%." . max( 0, 2 - floor( log10( $decimal ) ) ) . "f", $decimal );
 189          // Then remove any trailing 0's
 190          return preg_replace( '/\.?0*$/', '', $percent );
 191      }
 192  
 193      /**
 194       * Given a mime type, return a comma separated list of allowed extensions.
 195       *
 196       * @param $mime String mime type
 197       * @return String Comma separated list of allowed extensions (e.g. ".ogg, .oga")
 198       */
 199  	private function getExtensionList( $mime ) {
 200          $exts = MimeMagic::singleton()->getExtensionsForType( $mime );
 201          if ( $exts === null ) {
 202              return '';
 203          }
 204          $extArray = explode( ' ', $exts );
 205          $extArray = array_unique( $extArray );
 206          foreach ( $extArray as &$ext ) {
 207              $ext = '.' . $ext;
 208          }
 209  
 210          return $this->getLanguage()->commaList( $extArray );
 211      }
 212  
 213      /**
 214       * Output the start of the table
 215       *
 216       * Including opening <table>, and first <tr> with column headers.
 217       */
 218  	protected function outputTableStart( $mediaType ) {
 219          $this->getOutput()->addHTML(
 220              Html::openElement(
 221                  'table',
 222                  array( 'class' => array(
 223                      'mw-mediastats-table',
 224                      'mw-mediastats-table-' . strtolower( $mediaType ),
 225                      'sortable',
 226                      'wikitable'
 227                  ))
 228              )
 229          );
 230          $this->getOutput()->addHTML( $this->getTableHeaderRow() );
 231      }
 232  
 233      /**
 234       * Get (not output) the header row for the table
 235       *
 236       * @return String the header row of the able
 237       */
 238  	protected function getTableHeaderRow() {
 239          $headers = array( 'mimetype', 'extensions', 'count', 'totalbytes' );
 240          $ths = '';
 241          foreach ( $headers as $header ) {
 242              $ths .= Html::rawElement(
 243                  'th',
 244                  array(),
 245                  // for grep:
 246                  // mediastatistics-table-mimetype, mediastatistics-table-extensions
 247                  // tatistics-table-count, mediastatistics-table-totalbytes
 248                  $this->msg( 'mediastatistics-table-' . $header )->parse()
 249              );
 250          }
 251          return Html::rawElement( 'tr', array(), $ths );
 252      }
 253  
 254      /**
 255       * Output a header for a new media type section
 256       *
 257       * @param $mediaType string A media type (e.g. from the MEDIATYPE_xxx constants)
 258       */
 259  	protected function outputMediaType( $mediaType ) {
 260          $this->getOutput()->addHTML(
 261              Html::element(
 262                  'h2',
 263                  array( 'class' => array(
 264                      'mw-mediastats-mediatype',
 265                      'mw-mediastats-mediatype-' . strtolower( $mediaType )
 266                  )),
 267                  // for grep
 268                  // mediastatistics-header-unknown, mediastatistics-header-bitmap,
 269                  // mediastatistics-header-drawing, mediastatistics-header-audio,
 270                  // mediastatistics-header-video, mediastatistics-header-multimedia,
 271                  // mediastatistics-header-office, mediastatistics-header-text,
 272                  // mediastatistics-header-executable, mediastatistics-header-archive,
 273                  $this->msg( 'mediastatistics-header-' . strtolower( $mediaType ) )->text()
 274              )
 275          );
 276          /** @todo Possibly could add a message here explaining what the different types are.
 277           *    not sure if it is needed though.
 278           */
 279      }
 280  
 281      /**
 282       * parse the fake title format that this special page abuses querycache with.
 283       *
 284       * @param $fakeTitle String A string formatted as <media type>;<mime type>;<count>;<bytes>
 285       * @return Array The constituant parts of $fakeTitle
 286       */
 287  	private function splitFakeTitle( $fakeTitle ) {
 288          return explode( ';', $fakeTitle, 4 );
 289      }
 290  
 291      /**
 292       * What group to put the page in
 293       * @return string
 294       */
 295  	protected function getGroupName() {
 296          return 'media';
 297      }
 298  
 299      /**
 300       * This method isn't used, since we override outputResults, but
 301       * we need to implement since abstract in parent class.
 302       *
 303       * @param $skin Skin
 304       * @param $result stdObject Result row
 305       */
 306  	public function formatResult( $skin, $result ) {
 307          throw new MWException( "unimplemented" );
 308      }
 309  
 310      /**
 311       * Initialize total values so we can figure out percentages later.
 312       *
 313       * @param $dbr DatabaseBase
 314       * @param $res ResultWrapper
 315       */
 316  	public function preprocessResults( $dbr, $res ) {
 317          $this->totalCount = $this->totalBytes = 0;
 318          foreach ( $res as $row ) {
 319              list( , , $count, $bytes ) = $this->splitFakeTitle( $row->title );
 320              $this->totalCount += $count;
 321              $this->totalBytes += $bytes;
 322          }
 323          $res->seek( 0 );
 324      }
 325  }


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