limit = 5000; $this->shownavigation = false; } function isExpensive() { return true; } /** * Query to do. * * This abuses the query cache table by storing mime types as "titles". * * This will store entries like [[Media:BITMAP;image/jpeg;200;20000]] * where the form is Media type;mime type;count;bytes. * * This relies on the behaviour that when value is tied, the order things * come out of querycache table is the order they went in. Which is hacky. * However, other special pages like Special:Deadendpages and * Special:BrokenRedirects also rely on this. */ public function getQueryInfo() { $dbr = wfGetDB( DB_SLAVE ); $fakeTitle = $dbr->buildConcat( array( 'img_media_type', $dbr->addQuotes( ';' ), 'img_major_mime', $dbr->addQuotes( '/' ), 'img_minor_mime', $dbr->addQuotes( ';' ), 'COUNT(*)', $dbr->addQuotes( ';' ), 'SUM( img_size )' ) ); return array( 'tables' => array( 'image' ), 'fields' => array( 'title' => $fakeTitle, 'namespace' => NS_MEDIA, /* needs to be something */ 'value' => '1' ), 'conds' => array( // WMF has a random null row in the db 'img_media_type IS NOT NULL' ), 'options' => array( 'GROUP BY' => array( 'img_media_type', 'img_major_mime', 'img_minor_mime', ) ) ); } /** * How to sort the results * * It's important that img_media_type come first, otherwise the * tables will be fragmented. * @return Array Fields to sort by */ function getOrderFields() { return array( 'img_media_type', 'count(*)', 'img_major_mime', 'img_minor_mime' ); } /** * Output the results of the query. * * @param $out OutputPage * @param $skin Skin (deprecated presumably) * @param $dbr IDatabase * @param $res ResultWrapper Results from query * @param $num integer Number of results * @param $offset integer Paging offset (Should always be 0 in our case) */ protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) { $prevMediaType = null; foreach ( $res as $row ) { list( $mediaType, $mime, $totalCount, $totalBytes ) = $this->splitFakeTitle( $row->title ); if ( $prevMediaType !== $mediaType ) { if ( $prevMediaType !== null ) { // We're not at beginning, so we have to // close the previous table. $this->outputTableEnd(); } $this->outputMediaType( $mediaType ); $this->outputTableStart( $mediaType ); $prevMediaType = $mediaType; } $this->outputTableRow( $mime, intval( $totalCount ), intval( $totalBytes ) ); } if ( $prevMediaType !== null ) { $this->outputTableEnd(); } } /** * Output closing */ protected function outputTableEnd() { $this->getOutput()->addHtml( Html::closeElement( 'table' ) ); } /** * Output a row of the stats table * * @param $mime String mime type (e.g. image/jpeg) * @param $count integer Number of images of this type * @param $totalBytes integer Total space for images of this type */ protected function outputTableRow( $mime, $count, $bytes ) { $mimeSearch = SpecialPage::getTitleFor( 'MIMEsearch', $mime ); $row = Html::rawElement( 'td', array(), Linker::link( $mimeSearch, htmlspecialchars( $mime ) ) ); $row .= Html::element( 'td', array(), $this->getExtensionList( $mime ) ); $row .= Html::rawElement( 'td', // Make sure js sorts it in numeric order array( 'data-sort-value' => $count ), $this->msg( 'mediastatistics-nfiles' ) ->numParams( $count ) /** @todo Check to be sure this really should have number formatting */ ->numParams( $this->makePercentPretty( $count / $this->totalCount ) ) ->parse() ); $row .= Html::rawElement( 'td', // Make sure js sorts it in numeric order array( 'data-sort-value' => $bytes ), $this->msg( 'mediastatistics-nbytes' ) ->numParams( $bytes ) ->sizeParams( $bytes ) /** @todo Check to be sure this really should have number formatting */ ->numParams( $this->makePercentPretty( $bytes / $this->totalBytes ) ) ->parse() ); $this->getOutput()->addHTML( Html::rawElement( 'tr', array(), $row ) ); } /** * @param float $decimal A decimal percentage (ie for 12.3%, this would be 0.123) * @return String The percentage formatted so that 3 significant digits are shown. */ protected function makePercentPretty( $decimal ) { $decimal *= 100; // Always show three useful digits if ( $decimal == 0 ) { return '0'; } if ( $decimal >= 100 ) { return '100'; } $percent = sprintf( "%." . max( 0, 2 - floor( log10( $decimal ) ) ) . "f", $decimal ); // Then remove any trailing 0's return preg_replace( '/\.?0*$/', '', $percent ); } /** * Given a mime type, return a comma separated list of allowed extensions. * * @param $mime String mime type * @return String Comma separated list of allowed extensions (e.g. ".ogg, .oga") */ private function getExtensionList( $mime ) { $exts = MimeMagic::singleton()->getExtensionsForType( $mime ); if ( $exts === null ) { return ''; } $extArray = explode( ' ', $exts ); $extArray = array_unique( $extArray ); foreach ( $extArray as &$ext ) { $ext = '.' . $ext; } return $this->getLanguage()->commaList( $extArray ); } /** * Output the start of the table * * Including opening