r97249 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r97248‎ | r97249 | r97250 >
Date:09:50, 16 September 2011
Author:nikerabbit
Status:deferred
Tags:
Comment:
Allow specifying start date for graphs. Adapted from Wikia code.
Modified paths:
  • /trunk/extensions/Translate/specials/SpecialTranslationStats.php (modified) (history)

Diff [purge]

Index: trunk/extensions/Translate/specials/SpecialTranslationStats.php
@@ -37,6 +37,7 @@
3838 $opts->add( 'height', 400 );
3939 $opts->add( 'group', '' );
4040 $opts->add( 'uselang', '' );
 41+ $opts->add( 'start', '' );
4142 $opts->fetchValuesFromRequest( $wgRequest );
4243
4344 $pars = explode( ';', $par );
@@ -55,6 +56,9 @@
5657 $opts->validateIntBounds( 'days', 1, 10000 );
5758 $opts->validateIntBounds( 'width', 200, 1000 );
5859 $opts->validateIntBounds( 'height', 200, 1000 );
 60+ if ( $opts['start'] !== '' ) {
 61+ $opts['start'] = strval( wfTimestamp( TS_MW, $opts['start'] ) );
 62+ }
5963
6064 $validScales = array( 'months', 'weeks', 'days', 'hours' );
6165 if ( !in_array( $opts['scale'], $validScales ) ) {
@@ -126,6 +130,7 @@
127131 $this->eInput( 'width', $opts ) .
128132 $this->eInput( 'height', $opts ) .
129133 '<tr><td colspan="2"><hr /></td></tr>' .
 134+ $this->eInput( 'start', $opts, 12 ) .
130135 $this->eInput( 'days', $opts ) .
131136 $this->eRadio( 'scale', $opts, array( 'months', 'weeks', 'days', 'hours' ) ) .
132137 $this->eRadio( 'count', $opts, array( 'edits', 'users', 'registrations' ) ) .
@@ -182,12 +187,12 @@
183188 * @param $opts FormOptions
184189 * @return \string Html.
185190 */
186 - protected function eInput( $name, FormOptions $opts ) {
 191+ protected function eInput( $name, FormOptions $opts, $width = 4 ) {
187192 $value = $opts[$name];
188193
189194 return
190195 '<tr><td>' . $this->eLabel( $name ) . '</td><td>' .
191 - Xml::input( $name, 4, $value, array( 'id' => $name ) ) .
 196+ Xml::input( $name, $width, $value, array( 'id' => $name ) ) .
192197 '</td></tr>' . "\n";
193198 }
194199
@@ -354,37 +359,33 @@
355360 $so = new TranslatePerLanguageStats( $opts );
356361 }
357362
 363+ $fixedStart = $opts->getValue( 'start' ) !== '';
 364+
358365 $now = time();
 366+ $period = 3600 * 24 * $opts->getValue( 'days' );
359367
360 - /* Ensure that the first item in the graph has full data even
361 - * if it doesn't align with the given 'days' boundary */
362 - $cutoff = $now - ( 3600 * 24 * $opts->getValue( 'days' ) );
363 - if ( $opts['scale'] === 'hours' ) {
364 - $cutoff -= ( $cutoff % 3600 );
365 - } elseif ( $opts['scale'] === 'days' ) {
366 - $cutoff -= ( $cutoff % 86400 );
367 - } elseif ( $opts['scale'] === 'weeks' ) {
368 - /* Here we assume that week starts on monday, which does not
369 - * always hold true. Go backwards day by day until we are on monday */
370 - while ( date( 'D', $cutoff ) !== "Mon" ) {
371 - $cutoff -= 86400;
372 - }
373 - $cutoff -= ( $cutoff % 86400 );
374 - } elseif ( $opts['scale'] === 'months' ) {
375 - // Go backwards day by day until we are on the first day of the month
376 - while ( date( 'j', $cutoff ) !== "1" ) {
377 - $cutoff -= 86400;
378 - }
379 - $cutoff -= ( $cutoff % 86400 );
 368+ if ( $fixedStart ) {
 369+ $cutoff = wfTimestamp( TS_UNIX, $opts->getValue( 'start' ) );
 370+ } else {
 371+ $cutoff = $now - $period;
380372 }
 373+ $cutoff = self::roundTimestampToCutoff( $opts['scale'], $cutoff, 'earlier' );
381374
 375+ $start = $cutoff;
 376+
 377+ if ( $fixedStart ) {
 378+ $end = self::roundTimestampToCutoff( $opts['scale'], $start + $period, 'later' ) -1;
 379+ } else {
 380+ $end = null;
 381+ }
 382+
382383 $tables = array();
383384 $fields = array();
384385 $conds = array();
385386 $type = __METHOD__;
386387 $options = array();
387388
388 - $so->preQuery( $tables, $fields, $conds, $type, $options, $cutoff );
 389+ $so->preQuery( $tables, $fields, $conds, $type, $options, $start, $end );
389390 $res = $dbr->select( $tables, $fields, $conds, $type, $options );
390391 wfDebug( __METHOD__ . "-queryend\n" );
391392
@@ -399,7 +400,8 @@
400401
401402 $data = array();
402403 // Allow 10 seconds in the future for processing time
403 - while ( $cutoff <= $now + 10 ) {
 404+ $lastValue = $end !== null ? $end : $now + 10;
 405+ while ( $cutoff <= $lastValue ) {
404406 $date = $wgLang->sprintfDate( $dateFormat, wfTimestamp( TS_MW, $cutoff ) );
405407 $cutoff += $increment;
406408 $data[$date] = $defaults;
@@ -450,14 +452,59 @@
451453 }
452454 }
453455
 456+ if ( $end == null ) {
 457+ $last = array_splice( $data, -1, 1 );
 458+ // Indicator that the last value is not full
 459+ $data[key( $last ) . '*'] = current( $last );
 460+ }
454461
455 - $last = array_splice( $data, -1, 1 );
456 - $data[key( $last ) . '*'] = current( $last );
457 -
458462 return array( $labels, $data );
459463 }
460464
461465 /**
 466+ * Gets the closest earlieast timestamp that corresponds to start of a
 467+ * period in given scale, like, midnight, monday or first day of the month.
 468+ * @param $scale string One of hours, days, weeks, months
 469+ * @param $cutoff int Timestamp in unix format.
 470+ * @param $direction string One of earlier, later
 471+ */
 472+ protected static function roundTimestampToCutoff( $scale, $cutoff, $direction = 'earlier' ) {
 473+ $dir = $direction === 'earlier' ? -1 : 1;
 474+
 475+ /* Ensure that the first item in the graph has full data even
 476+ * if it doesn't align with the given 'days' boundary */
 477+ if ( $scale === 'hours' ) {
 478+ $cutoff += self::roundingAddition( $cutoff, 3600, $dir );
 479+ } elseif ( $scale === 'days' ) {
 480+ $cutoff += self::roundingAddition( $cutoff, 86400, $dir );
 481+ } elseif ( $scale === 'weeks' ) {
 482+ /* Here we assume that week starts on monday, which does not
 483+ * always hold true. Go Xwards day by day until we are on monday */
 484+ while ( date( 'D', $cutoff ) !== "Mon" ) {
 485+ $cutoff += $dir*86400;
 486+ }
 487+ // Round to nearest day
 488+ $cutoff -= ( $cutoff % 86400 );
 489+ } elseif ( $scale === 'months' ) {
 490+ // Go Xwards/ day by day until we are on the first day of the month
 491+ while ( date( 'j', $cutoff ) !== "1" ) {
 492+ $cutoff += $dir*86400;
 493+ }
 494+ // Round to nearest day
 495+ $cutoff -= ( $cutoff % 86400 );
 496+ }
 497+ return $cutoff;
 498+ }
 499+
 500+ protected static function roundingAddition( $ts, $amount, $dir ) {
 501+ if ( $direction === -1 ) {
 502+ return -1 * ( $ts % $amount );
 503+ } else {
 504+ return $amount - ( $ts % $amount );
 505+ }
 506+ }
 507+
 508+ /**
462509 * Adds raw image data of the graph to the output.
463510 * @param $opts FormOptions
464511 */
@@ -601,9 +648,10 @@
602649 * @param $conds \array Empty array. Append select conditions.
603650 * @param $type \string Append graph type (used to identify queries).
604651 * @param $options \array Empty array. Append extra query options.
605 - * @param $cutoff \string Precalculated cutoff timestamp in unix format.
 652+ * @param $start \string Precalculated start cutoff timestamp
 653+ * @param $end \string Precalculated end cutoff timestamp
606654 */
607 - public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $cutoff );
 655+ public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $start, $end );
608656
609657 /**
610658 * Return the indexes which this result contributes to.
@@ -667,6 +715,18 @@
668716
669717 return $dateFormat;
670718 }
 719+
 720+ protected static function makeTimeCondition( $field, $start, $end ) {
 721+ $db = wfGetDB( DB_SLAVE );
 722+ $conds = array();
 723+ if ( $start !== null ) {
 724+ $conds[] = "$field >= '{$db->timestamp( $start )}'";
 725+ }
 726+ if ( $end !== null ) {
 727+ $conds[] = "$field <= '{$db->timestamp( $end )}'";
 728+ }
 729+ return $conds;
 730+ }
671731 }
672732
673733 /**
@@ -683,7 +743,7 @@
684744 $opts->validateIntBounds( 'days', 1, 200 );
685745 }
686746
687 - public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $cutoff ) {
 747+ public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $start, $end ) {
688748 global $wgTranslateMessageNamespaces;
689749
690750 $db = wfGetDB( DB_SLAVE );
@@ -692,11 +752,13 @@
693753 $fields = array( 'rc_timestamp' );
694754
695755 $conds = array(
696 - "rc_timestamp >= '{$db->timestamp( $cutoff )}'",
697756 'rc_namespace' => $wgTranslateMessageNamespaces,
698757 'rc_bot' => 0
699758 );
700759
 760+ $timeConds = self::makeTimeCondition( 'rc_timestamp', $start, $end );
 761+ $conds = array_merge( $conds, $timeConds );
 762+
701763 $options = array( 'ORDER BY' => 'rc_timestamp' );
702764
703765 $this->groups = array_filter( array_map( 'trim', explode( ',', $this->opts['group'] ) ) );
@@ -863,11 +925,11 @@
864926 * @ingroup Stats
865927 */
866928 class TranslateRegistrationStats extends TranslationStatsBase {
867 - public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $cutoff ) {
 929+ public function preQuery( &$tables, &$fields, &$conds, &$type, &$options, $start, $end ) {
868930 $db = wfGetDB( DB_SLAVE );
869931 $tables = 'user';
870932 $fields = 'user_registration';
871 - $conds = array( "user_registration >= '{$db->timestamp( $cutoff )}'" );
 933+ $conds = self::makeTimeCondition( 'user_registration', $start, $end );
872934 $type .= '-registration';
873935 $options = array();
874936 }

Status & tagging log