Index: trunk/extensions/Translate/SpecialTranslationStats.php |
— | — | @@ -14,10 +14,9 @@ |
15 | 15 | * @ingroup SpecialPage |
16 | 16 | * @todo Needs documentation. |
17 | 17 | */ |
18 | | -class SpecialTranslationStats extends SpecialPage { |
| 18 | +class SpecialTranslationStats extends IncludableSpecialPage { |
19 | 19 | public function __construct() { |
20 | 20 | parent::__construct( 'TranslationStats' ); |
21 | | - $this->includable( true ); |
22 | 21 | } |
23 | 22 | |
24 | 23 | public function execute( $par ) { |
— | — | @@ -37,11 +36,16 @@ |
38 | 37 | $opts->fetchValuesFromRequest( $wgRequest ); |
39 | 38 | |
40 | 39 | $pars = explode( ';', $par ); |
| 40 | + |
41 | 41 | foreach ( $pars as $item ) { |
42 | | - if ( strpos( $item, '=' ) === false ) continue; |
| 42 | + if ( strpos( $item, '=' ) === false ) { |
| 43 | + continue; |
| 44 | + } |
| 45 | + |
43 | 46 | list( $key, $value ) = array_map( 'trim', explode( '=', $item, 2 ) ); |
44 | | - if ( isset( $opts[$key] ) ) |
| 47 | + if ( isset( $opts[$key] ) ) { |
45 | 48 | $opts[$key] = $value; |
| 49 | + } |
46 | 50 | } |
47 | 51 | |
48 | 52 | $opts->validateIntBounds( 'days', 1, 10000 ); |
— | — | @@ -49,11 +53,18 @@ |
50 | 54 | $opts->validateIntBounds( 'height', 200, 1000 ); |
51 | 55 | |
52 | 56 | $validScales = array( 'months', 'weeks', 'days', 'hours' ); |
53 | | - if ( !in_array( $opts['scale'], $validScales ) ) $opts['scale'] = 'days'; |
54 | | - if ( $opts['scale'] === 'hours' ) $opts->validateIntBounds( 'days', 1, 4 ); |
| 57 | + if ( !in_array( $opts['scale'], $validScales ) ) { |
| 58 | + $opts['scale'] = 'days'; |
| 59 | + } |
55 | 60 | |
| 61 | + if ( $opts['scale'] === 'hours' ) { |
| 62 | + $opts->validateIntBounds( 'days', 1, 4 ); |
| 63 | + } |
| 64 | + |
56 | 65 | $validCounts = array( 'edits', 'users', 'registrations' ); |
57 | | - if ( !in_array( $opts['count'], $validCounts ) ) $opts['count'] = 'edits'; |
| 66 | + if ( !in_array( $opts['count'], $validCounts ) ) { |
| 67 | + $opts['count'] = 'edits'; |
| 68 | + } |
58 | 69 | |
59 | 70 | foreach ( array( 'group', 'language' ) as $t ) { |
60 | 71 | $values = array_map( 'trim', explode( ',', $opts[$t] ) ); |
— | — | @@ -70,7 +81,10 @@ |
71 | 82 | // Cache for two hours |
72 | 83 | if ( !$opts['preview'] ) { |
73 | 84 | $lastMod = $wgOut->checkLastModified( wfTimestamp( TS_MW, time() - 2 * 3600 ) ); |
74 | | - if ( $lastMod ) return; |
| 85 | + |
| 86 | + if ( $lastMod ) { |
| 87 | + return; |
| 88 | + } |
75 | 89 | } |
76 | 90 | |
77 | 91 | if ( !$wgRequest->getBool( 'debug' ) ) { |
— | — | @@ -124,16 +138,26 @@ |
125 | 139 | '</fieldset>' |
126 | 140 | ); |
127 | 141 | |
128 | | - if ( !$opts['preview'] ) return; |
| 142 | + if ( !$opts['preview'] ) { |
| 143 | + return; |
| 144 | + } |
129 | 145 | |
130 | 146 | $spiParams = ''; |
131 | 147 | foreach ( $opts->getChangedValues() as $key => $v ) { |
132 | | - if ( $key === 'preview' ) continue; |
133 | | - if ( $spiParams !== '' ) $spiParams .= ';'; |
| 148 | + if ( $key === 'preview' ) { |
| 149 | + continue; |
| 150 | + } |
| 151 | + |
| 152 | + if ( $spiParams !== '' ) { |
| 153 | + $spiParams .= ';'; |
| 154 | + } |
| 155 | + |
134 | 156 | $spiParams .= wfEscapeWikiText( "$key=$v" ); |
135 | 157 | } |
136 | 158 | |
137 | | - if ( $spiParams !== '' ) $spiParams = '/' . $spiParams; |
| 159 | + if ( $spiParams !== '' ) { |
| 160 | + $spiParams = '/' . $spiParams; |
| 161 | + } |
138 | 162 | |
139 | 163 | $titleText = $this->getTitle()->getPrefixedText(); |
140 | 164 | |
— | — | @@ -160,6 +184,7 @@ |
161 | 185 | protected function eLabel( $name ) { |
162 | 186 | $label = 'translate-statsf-' . $name; |
163 | 187 | $label = wfMsgExt( $label, array( 'parsemag', 'escapenoentities' ) ); |
| 188 | + |
164 | 189 | return Xml::tags( 'label', array( 'for' => $name ), $label ); |
165 | 190 | } |
166 | 191 | |
— | — | @@ -177,8 +202,8 @@ |
178 | 203 | } |
179 | 204 | |
180 | 205 | $s .= implode( ' ', $options ); |
| 206 | + $s .= '</td></tr>' . "\n"; |
181 | 207 | |
182 | | - $s .= '</td></tr>' . "\n"; |
183 | 208 | return $s; |
184 | 209 | } |
185 | 210 | |
— | — | @@ -249,6 +274,7 @@ |
250 | 275 | |
251 | 276 | $jsSelect = new JsSelectToInput( $selector ); |
252 | 277 | $jsSelect->setSourceId( 'mw-group-selector' ); |
| 278 | + |
253 | 279 | return $jsSelect; |
254 | 280 | } |
255 | 281 | |
— | — | @@ -256,6 +282,7 @@ |
257 | 283 | $title = $this->getTitle(); |
258 | 284 | $cgiparams = wfArrayToCgi( array( 'graphit' => true ), $opts->getAllValues() ); |
259 | 285 | $href = $title->getLocalUrl( $cgiparams ); |
| 286 | + |
260 | 287 | return Xml::element( 'img', |
261 | 288 | array( |
262 | 289 | 'src' => $href, |
— | — | @@ -276,6 +303,7 @@ |
277 | 304 | } |
278 | 305 | |
279 | 306 | $now = time(); |
| 307 | + |
280 | 308 | /* Ensure that the first item in the graph has full data even |
281 | 309 | * if it doesn't align with the given 'days' boundary */ |
282 | 310 | $cutoff = $now - ( 3600 * 24 * $opts->getValue( 'days' ) ); |
— | — | @@ -286,11 +314,15 @@ |
287 | 315 | } elseif ( $opts['scale'] === 'weeks' ) { |
288 | 316 | /* Here we assume that week starts on monday, which does not |
289 | 317 | * always hold true. Go backwards day by day until we are on monday */ |
290 | | - while ( date( 'D', $cutoff ) !== "Mon" ) { $cutoff -= 86400; } |
| 318 | + while ( date( 'D', $cutoff ) !== "Mon" ) { |
| 319 | + $cutoff -= 86400; |
| 320 | + } |
291 | 321 | $cutoff -= ( $cutoff % 86400 ); |
292 | 322 | } elseif ( $opts['scale'] === 'months' ) { |
293 | 323 | // Go backwards day by day until we are on the first day of the month |
294 | | - while ( date( 'j', $cutoff ) !== "1" ) { $cutoff -= 86400; } |
| 324 | + while ( date( 'j', $cutoff ) !== "1" ) { |
| 325 | + $cutoff -= 86400; |
| 326 | + } |
295 | 327 | $cutoff -= ( $cutoff % 86400 ); |
296 | 328 | } |
297 | 329 | |
— | — | @@ -323,15 +355,24 @@ |
324 | 356 | |
325 | 357 | // Processing |
326 | 358 | $labelToIndex = array_flip( $labels ); |
| 359 | + |
327 | 360 | foreach ( $res as $row ) { |
328 | 361 | $indexLabels = $so->indexOf( $row ); |
329 | | - if ( $indexLabels === false ) continue; |
| 362 | + if ( $indexLabels === false ) { |
| 363 | + continue; |
| 364 | + } |
330 | 365 | |
331 | 366 | foreach ( (array) $indexLabels as $i ) { |
332 | | - if ( !isset( $labelToIndex[$i] ) ) continue; |
| 367 | + if ( !isset( $labelToIndex[$i] ) ) { |
| 368 | + continue; |
| 369 | + |
| 370 | + } |
333 | 371 | $date = $wgLang->sprintfDate( $dateFormat, $so->getTimestamp( $row ) ); |
334 | 372 | // Ignore values outside range |
335 | | - if ( !isset( $data[$date] ) ) continue; |
| 373 | + if ( !isset( $data[$date] ) ) { |
| 374 | + continue; |
| 375 | + } |
| 376 | + |
336 | 377 | $data[$date][$labelToIndex[$i]]++; |
337 | 378 | } |
338 | 379 | } |
— | — | @@ -359,19 +400,23 @@ |
360 | 401 | $count = count( $resData ); |
361 | 402 | $skip = intval( $count / ( $width / 60 ) - 1 ); |
362 | 403 | $i = $count; |
| 404 | + |
363 | 405 | foreach ( $resData as $date => $edits ) { |
364 | 406 | if ( $skip > 0 ) { |
365 | 407 | if ( ( $count - $i ) % $skip !== 0 ) $date = ''; |
366 | 408 | } |
| 409 | + |
367 | 410 | if ( strpos( $date, ';' ) !== false ) { |
368 | 411 | list( , $date ) = explode( ';', $date, 2 ); |
369 | 412 | } |
| 413 | + |
370 | 414 | array_unshift( $edits, $date ); |
371 | 415 | $data[] = $edits; |
372 | 416 | $i--; |
373 | 417 | } |
374 | 418 | |
375 | 419 | $font = FCFontFinder::find( $wgLang->getCode() ); |
| 420 | + |
376 | 421 | if ( $font ) { |
377 | 422 | $plot->SetDefaultTTFont( $font ); |
378 | 423 | } else { |
— | — | @@ -379,8 +424,9 @@ |
380 | 425 | } |
381 | 426 | $plot->SetDataValues( $data ); |
382 | 427 | |
383 | | - if ( $legend !== null ) |
| 428 | + if ( $legend !== null ) { |
384 | 429 | $plot->SetLegend( $legend ); |
| 430 | + } |
385 | 431 | |
386 | 432 | $numberFont = FCFontFinder::find( 'en' ); |
387 | 433 | |
— | — | @@ -401,7 +447,10 @@ |
402 | 448 | $max = round( $max, intval( -log( $max, 10 ) ) ); |
403 | 449 | |
404 | 450 | $yTick = 10; |
405 | | - while ( $max / $yTick > $height / 20 ) $yTick *= 2; |
| 451 | + while ( $max / $yTick > $height / 20 ) { |
| 452 | + $yTick *= 2; |
| 453 | + } |
| 454 | + |
406 | 455 | // If we have very small case, ensure that there is at least one tick |
407 | 456 | $yTick = min( $max, $yTick ); |
408 | 457 | $yTick = self::roundToSignificant( $yTick ); |
— | — | @@ -434,6 +483,7 @@ |
435 | 484 | } elseif ( $scale === 'hours' ) { |
436 | 485 | $increment = 3600; |
437 | 486 | } |
| 487 | + |
438 | 488 | return $increment; |
439 | 489 | } |
440 | 490 | } |
— | — | @@ -480,6 +530,7 @@ |
481 | 531 | } elseif ( $this->opts['scale'] === 'hours' ) { |
482 | 532 | $dateFormat .= ';H'; |
483 | 533 | } |
| 534 | + |
484 | 535 | return $dateFormat; |
485 | 536 | } |
486 | 537 | } |
— | — | @@ -542,9 +593,15 @@ |
543 | 594 | } |
544 | 595 | |
545 | 596 | $fields[] = 'rc_title'; |
546 | | - if ( $this->groups ) $fields[] = 'rc_namespace'; |
547 | | - if ( $this->opts['count'] === 'users' ) $fields[] = 'rc_user_text'; |
548 | 597 | |
| 598 | + if ( $this->groups ) { |
| 599 | + $fields[] = 'rc_namespace'; |
| 600 | + } |
| 601 | + |
| 602 | + if ( $this->opts['count'] === 'users' ) { |
| 603 | + $fields[] = 'rc_user_text'; |
| 604 | + } |
| 605 | + |
549 | 606 | $type .= '-perlang'; |
550 | 607 | } |
551 | 608 | |
— | — | @@ -565,12 +622,16 @@ |
566 | 623 | /** |
567 | 624 | * Do not consider language-less pages. |
568 | 625 | */ |
569 | | - if ( strpos( $row->rc_title, '/' ) === false ) return false; |
| 626 | + if ( strpos( $row->rc_title, '/' ) === false ) { |
| 627 | + return false; |
| 628 | + } |
570 | 629 | |
571 | 630 | /** |
572 | 631 | * No filters, just one key to track. |
573 | 632 | */ |
574 | | - if ( !$this->groups && !$this->codes ) return 'all'; |
| 633 | + if ( !$this->groups && !$this->codes ) { |
| 634 | + return 'all'; |
| 635 | + } |
575 | 636 | |
576 | 637 | /** |
577 | 638 | * The key-building needs to be in sync with ::labels(). |
— | — | @@ -592,6 +653,7 @@ |
593 | 654 | if ( $this->codes ) { |
594 | 655 | $codes = array( $code ); |
595 | 656 | } |
| 657 | + |
596 | 658 | return $this->combineTwoArrays( $groups, $codes ); |
597 | 659 | } |
598 | 660 | |
— | — | @@ -619,25 +681,38 @@ |
620 | 682 | } |
621 | 683 | |
622 | 684 | protected function combineTwoArrays( $groups, $codes ) { |
623 | | - if ( !count( $groups ) ) $groups[] = false; |
624 | | - if ( !count( $codes ) ) $codes[] = false; |
| 685 | + if ( !count( $groups ) ) { |
| 686 | + $groups[] = false; |
| 687 | + } |
625 | 688 | |
| 689 | + if ( !count( $codes ) ) { |
| 690 | + $codes[] = false; |
| 691 | + } |
| 692 | + |
626 | 693 | $items = array(); |
627 | 694 | foreach ( $groups as $group ) { |
628 | | - foreach ( $codes as $code ) { |
629 | | - $items[] = $this->makeLabel( $group, $code ); |
| 695 | + foreach ( $codes as $code ) { |
| 696 | + $items[] = $this->makeLabel( $group, $code ); |
| 697 | + } |
630 | 698 | } |
631 | | - } |
632 | 699 | return $items; |
633 | 700 | } |
634 | 701 | |
635 | 702 | protected function formatTimestamp( $timestamp ) { |
636 | 703 | global $wgContLang; |
| 704 | + |
637 | 705 | switch ( $this->opts['scale'] ) { |
638 | | - case 'hours' : $cut = 4; break; |
639 | | - case 'days' : $cut = 6; break; |
640 | | - case 'months': $cut = 8; break; |
641 | | - default : return $wgContLang->sprintfDate( $this->getDateFormat(), $timestamp ); |
| 706 | + case 'hours' : |
| 707 | + $cut = 4; |
| 708 | + break; |
| 709 | + case 'days' : |
| 710 | + $cut = 6; |
| 711 | + break; |
| 712 | + case 'months': |
| 713 | + $cut = 8; |
| 714 | + break; |
| 715 | + default : |
| 716 | + return $wgContLang->sprintfDate( $this->getDateFormat(), $timestamp ); |
642 | 717 | } |
643 | 718 | |
644 | 719 | return substr( $timestamp, 0, -$cut ); |