MediaWiki REL1_37
SpecialMediaStatistics.php
Go to the documentation of this file.
1<?php
29
34 protected $totalCount = 0, $totalBytes = 0;
35
39 protected $totalPerType = 0;
40
44 protected $countPerType = 0;
45
49 protected $totalSize = 0;
50
53
59 public function __construct(
60 MimeAnalyzer $mimeAnalyzer,
63 ) {
64 parent::__construct( 'MediaStatistics' );
65 // Generally speaking there is only a small number of file types,
66 // so just show all of them.
67 $this->limit = 5000;
68 $this->shownavigation = false;
69 $this->mimeAnalyzer = $mimeAnalyzer;
70 $this->setDBLoadBalancer( $loadBalancer );
71 $this->setLinkBatchFactory( $linkBatchFactory );
72 }
73
74 public function isExpensive() {
75 return true;
76 }
77
92 public function getQueryInfo() {
93 $dbr = $this->getDBLoadBalancer()->getConnectionRef( ILoadBalancer::DB_REPLICA );
94 $fakeTitle = $dbr->buildConcat( [
95 'img_media_type',
96 $dbr->addQuotes( ';' ),
97 'img_major_mime',
98 $dbr->addQuotes( '/' ),
99 'img_minor_mime',
100 $dbr->addQuotes( ';' ),
101 $dbr->buildStringCast( 'COUNT(*)' ),
102 $dbr->addQuotes( ';' ),
103 $dbr->buildStringCast( 'SUM( img_size )' )
104 ] );
105 return [
106 'tables' => [ 'image' ],
107 'fields' => [
108 'title' => $fakeTitle,
109 'namespace' => NS_MEDIA, /* needs to be something */
110 'value' => '1'
111 ],
112 'options' => [
113 'GROUP BY' => [
114 'img_media_type',
115 'img_major_mime',
116 'img_minor_mime',
117 ]
118 ]
119 ];
120 }
121
129 protected function getOrderFields() {
130 return [ 'img_media_type', 'count(*)', 'img_major_mime', 'img_minor_mime' ];
131 }
132
143 protected function outputResults( $out, $skin, $dbr, $res, $num, $offset ) {
144 $prevMediaType = null;
145 foreach ( $res as $row ) {
146 $mediaStats = $this->splitFakeTitle( $row->title );
147 if ( count( $mediaStats ) < 4 ) {
148 continue;
149 }
150 list( $mediaType, $mime, $totalCount, $totalBytes ) = $mediaStats;
151 if ( $prevMediaType !== $mediaType ) {
152 if ( $prevMediaType !== null ) {
153 // We're not at beginning, so we have to
154 // close the previous table.
155 $this->outputTableEnd();
156 }
157 $this->outputMediaType( $mediaType );
158 $this->totalPerType = 0;
159 $this->countPerType = 0;
160 $this->outputTableStart( $mediaType );
161 $prevMediaType = $mediaType;
162 }
163 $this->outputTableRow( $mime, intval( $totalCount ), intval( $totalBytes ) );
164 }
165 if ( $prevMediaType !== null ) {
166 $this->outputTableEnd();
167 // add total size of all files
168 $this->outputMediaType( 'total' );
169 $this->getOutput()->addWikiTextAsInterface(
170 $this->msg( 'mediastatistics-allbytes' )
171 ->numParams( $this->totalSize )
172 ->sizeParams( $this->totalSize )
173 ->numParams( $this->totalCount )
174 ->text()
175 );
176 }
177 }
178
182 protected function outputTableEnd() {
183 $this->getOutput()->addHTML(
184 Html::closeElement( 'tbody' ) .
185 Html::closeElement( 'table' )
186 );
187 $this->getOutput()->addWikiTextAsInterface(
188 $this->msg( 'mediastatistics-bytespertype' )
189 ->numParams( $this->totalPerType )
190 ->sizeParams( $this->totalPerType )
191 ->numParams( $this->makePercentPretty( $this->totalPerType / $this->totalBytes ) )
192 ->numParams( $this->countPerType )
193 ->numParams( $this->makePercentPretty( $this->countPerType / $this->totalCount ) )
194 ->text()
195 );
196 $this->totalSize += $this->totalPerType;
197 }
198
206 protected function outputTableRow( $mime, $count, $bytes ) {
207 $mimeSearch = SpecialPage::getTitleFor( 'MIMEsearch', $mime );
209 $row = Html::rawElement(
210 'td',
211 [],
212 $linkRenderer->makeLink( $mimeSearch, $mime )
213 );
214 $row .= Html::rawElement(
215 'td',
216 [],
217 $this->getExtensionList( $mime )
218 );
219 $row .= Html::rawElement(
220 'td',
221 // Make sure js sorts it in numeric order
222 [ 'data-sort-value' => $count ],
223 $this->msg( 'mediastatistics-nfiles' )
224 ->numParams( $count )
226 ->numParams( $this->makePercentPretty( $count / $this->totalCount ) )
227 ->parse()
228 );
229 $row .= Html::rawElement(
230 'td',
231 // Make sure js sorts it in numeric order
232 [ 'data-sort-value' => $bytes ],
233 $this->msg( 'mediastatistics-nbytes' )
234 ->numParams( $bytes )
235 ->sizeParams( $bytes )
237 ->numParams( $this->makePercentPretty( $bytes / $this->totalBytes ) )
238 ->parse()
239 );
240 $this->totalPerType += $bytes;
241 $this->countPerType += $count;
242 $this->getOutput()->addHTML( Html::rawElement( 'tr', [], $row ) );
243 }
244
249 protected function makePercentPretty( $decimal ) {
250 $decimal *= 100;
251 // Always show three useful digits
252 if ( $decimal == 0 ) {
253 return '0';
254 }
255 if ( $decimal >= 100 ) {
256 return '100';
257 }
258 $percent = sprintf( "%." . max( 0, 2 - floor( log10( $decimal ) ) ) . "f", $decimal );
259 // Then remove any trailing 0's
260 return preg_replace( '/\.?0*$/', '', $percent );
261 }
262
269 private function getExtensionList( $mime ) {
270 $exts = $this->mimeAnalyzer->getExtensionsFromMimeType( $mime );
271 if ( !$exts ) {
272 return '';
273 }
274 foreach ( $exts as &$ext ) {
275 $ext = htmlspecialchars( '.' . $ext );
276 }
277
278 return $this->getLanguage()->commaList( $exts );
279 }
280
287 protected function outputTableStart( $mediaType ) {
288 $out = $this->getOutput();
289 $out->addModuleStyles( 'jquery.tablesorter.styles' );
290 $out->addModules( 'jquery.tablesorter' );
291 $out->addHTML(
292 Html::openElement(
293 'table',
294 [ 'class' => [
295 'mw-mediastats-table',
296 'mw-mediastats-table-' . strtolower( $mediaType ),
297 'sortable',
298 'wikitable'
299 ] ]
300 ) .
301 Html::rawElement( 'thead', [], $this->getTableHeaderRow() ) .
302 Html::openElement( 'tbody' )
303 );
304 }
305
311 protected function getTableHeaderRow() {
312 $headers = [ 'mimetype', 'extensions', 'count', 'totalbytes' ];
313 $ths = '';
314 foreach ( $headers as $header ) {
315 $ths .= Html::rawElement(
316 'th',
317 [],
318 // for grep:
319 // mediastatistics-table-mimetype, mediastatistics-table-extensions
320 // tatistics-table-count, mediastatistics-table-totalbytes
321 $this->msg( 'mediastatistics-table-' . $header )->parse()
322 );
323 }
324 return Html::rawElement( 'tr', [], $ths );
325 }
326
332 protected function outputMediaType( $mediaType ) {
333 $this->getOutput()->addHTML(
334 Html::element(
335 'h2',
336 [ 'class' => [
337 'mw-mediastats-mediatype',
338 'mw-mediastats-mediatype-' . strtolower( $mediaType )
339 ] ],
340 // for grep
341 // mediastatistics-header-unknown, mediastatistics-header-bitmap,
342 // mediastatistics-header-drawing, mediastatistics-header-audio,
343 // mediastatistics-header-video, mediastatistics-header-multimedia,
344 // mediastatistics-header-office, mediastatistics-header-text,
345 // mediastatistics-header-executable, mediastatistics-header-archive,
346 // mediastatistics-header-3d,
347 $this->msg( 'mediastatistics-header-' . strtolower( $mediaType ) )->text()
348 )
349 );
353 }
354
361 private function splitFakeTitle( $fakeTitle ) {
362 return explode( ';', $fakeTitle, 4 );
363 }
364
369 protected function getGroupName() {
370 return 'media';
371 }
372
383 public function formatResult( $skin, $result ) {
384 throw new MWException( "unimplemented" );
385 }
386
393 public function preprocessResults( $dbr, $res ) {
395 $this->totalCount = $this->totalBytes = 0;
396 foreach ( $res as $row ) {
397 $mediaStats = $this->splitFakeTitle( $row->title );
398 $this->totalCount += $mediaStats[2] ?? 0;
399 $this->totalBytes += $mediaStats[3] ?? 0;
400 }
401 $res->seek( 0 );
402 }
403}
const NS_MEDIA
Definition Defines.php:52
MediaWiki exception.
makeLink( $target, $text=null, array $extraAttribs=[], array $query=[])
This is a class for doing query pages; since they're almost all the same, we factor out some of the f...
Definition QueryPage.php:41
executeLBFromResultWrapper(IResultWrapper $res, $ns=null)
Creates a new LinkBatch object, adds all pages from the passed result wrapper (MUST include title and...
setDBLoadBalancer(ILoadBalancer $loadBalancer)
LinkBatchFactory null $linkBatchFactory
Definition QueryPage.php:74
int $offset
The offset and limit in use, as passed to the query() function.
Definition QueryPage.php:46
setLinkBatchFactory(LinkBatchFactory $linkBatchFactory)
getDBLoadBalancer()
ILoadBalancer null $loadBalancer
Definition QueryPage.php:71
formatResult( $skin, $result)
This method isn't used, since we override outputResults, but we need to implement since abstract in p...
splitFakeTitle( $fakeTitle)
parse the fake title format that this special page abuses querycache with.
getExtensionList( $mime)
Given a mime type, return a comma separated list of allowed extensions.
getGroupName()
What group to put the page in.
preprocessResults( $dbr, $res)
Initialize total values so we can figure out percentages later.
int $totalSize
Combined file size of all files.
int $totalPerType
Combined file size of all files in a section.
__construct(MimeAnalyzer $mimeAnalyzer, ILoadBalancer $loadBalancer, LinkBatchFactory $linkBatchFactory)
int $countPerType
Combined file count of all files in a section.
outputResults( $out, $skin, $dbr, $res, $num, $offset)
Output the results of the query.
outputTableStart( $mediaType)
Output the start of the table.
getTableHeaderRow()
Get (not output) the header row for the table.
outputTableRow( $mime, $count, $bytes)
Output a row of the stats table.
isExpensive()
Is this query expensive (for some definition of expensive)? Then we don't let it run in miser mode.
getOrderFields()
How to sort the results.
outputMediaType( $mediaType)
Output a header for a new media type section.
getOutput()
Get the OutputPage being used for this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
LinkRenderer null $linkRenderer
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getLanguage()
Shortcut to get user's language.
Basic database interface for live and lazy-loaded relation database handles.
Definition IDatabase.php:38
Database cluster connection, tracking, load balancing, and transaction manager interface.
Result wrapper for grabbing data queried from an IDatabase object.
$mime
Definition router.php:60
if(!is_readable( $file)) $ext
Definition router.php:48
$header