Revision: 51932 Author: catrope Date: 2009-06-15 21:28:58 +0000 (Mon, 15 Jun 2009)
Log Message: ----------- PrefStats: * Add Special:PrefStats for viewing statistics using a nice Google Chart; currently restricted because of query load * Fixes all over the place Modified Paths: -------------- trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.hooks.php trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.i18n.php trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.php trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.sql Added Paths: ----------- trunk/extensions/UsabilityInitiative/PrefStats/Prefstats.alias.php trunk/extensions/UsabilityInitiative/PrefStats/SpecialPrefStats.php Modified: trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.hooks.php =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.hooks.php 2009-06-15 21:21:25 UTC (rev 51931) +++ trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.hooks.php 2009-06-15 21:28:58 UTC (rev 51932) @@ -13,6 +13,7 @@ global $wgExtNewTables; $wgExtNewTables[] = array( 'prefstats', dirname( __FILE__ ) . '/PrefStats.sql' ); + return true; } public static function save( $user, &$options ) { @@ -22,33 +23,37 @@ $dbw = wfGetDb( DB_MASTER ); foreach ( $wgPrefStatsTrackPrefs as $pref => $value ) { - if ( isset( $options[$pref] ) && $options[$pref] == $value ) - // FIXME: if the user disables and re-enables, - // we're not tracking that + $start = $dbw->selectField( 'prefstats', + 'ps_start', array( + 'ps_user' => $user->getId(), + 'ps_pref' => $pref, + 'ps_end IS NULL' + ), __METHOD__ ); + if ( isset( $options[$pref] ) && $options[$pref] == $value && !$start) $dbw->insert( 'prefstats', array( 'ps_user' => $user->getId(), 'ps_pref' => $pref, 'ps_value' => $value, 'ps_start' => $dbw->timestamp( wfTimestamp() ), 'ps_end' => null, - 'ps_duration' => - 1 // hack + 'ps_duration' => null ), __METHOD__, array( 'IGNORE' ) ); - else { - $start = $dbw->selectField( 'prefstats', - 'ps_start', array( - 'ps_user' => $user->getId(), - 'ps_pref' => $pref - ), __METHOD__ ); + else if ( ( !isset( $options[$pref] ) || $options[$pref] != $value ) && $start ) { if ( $start ) { $duration = wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $start ); $dbw->update( 'prefstats', array( - 'ps_end' => $dbw->timestamp( wfTimestamp() ), - 'ps_duration' => $dbw->timestamp( $duration ) + 'ps_end' => $dbw->timestamp( wfTimestamp() ), + 'ps_duration' => $duration + ), array( + 'ps_user' => $user->getId(), + 'ps_pref' => $pref, + 'ps_start' => $dbw->timestamp( $start ) ), __METHOD__ ); } } } + return true; } } Modified: trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.i18n.php =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.i18n.php 2009-06-15 21:21:25 UTC (rev 51931) +++ trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.i18n.php 2009-06-15 21:28:58 UTC (rev 51932) @@ -1,6 +1,6 @@ <?php /** - * Internationalisation for Usability Initiative EditWarning extension + * Internationalisation for Usability Initiative PrefStats extension * * @file * @ingroup Extensions @@ -14,6 +14,10 @@ $messages['en'] = array( 'prefstats' => 'Preference statistics', 'prefstats-desc' => 'Track statistics about how many users have certain preferences enabled', + 'prefstats-title' => 'Preference statistics', + 'prefstats-list-intro' => 'Currently, the following preferences are being tracked. Click on one to view statistics about it.', + 'prefstats-list-elem' => '$1 = $2', + 'prefstats-stat-line' => '$1 users have had the preference enabled for between $2 and $3 seconds', ); /** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца)) Modified: trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.php =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.php 2009-06-15 21:21:25 UTC (rev 51931) +++ trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.php 2009-06-15 21:28:58 UTC (rev 51932) @@ -25,6 +25,10 @@ // Tracking multiple values of the same preference is not possible $wgPrefStatsTrackPrefs = array(); +$wgPrefStatsChartDimensions = '1000x300'; + +$wgPrefStatsTimeUnit = 60*60; // one hour + /* Setup */ // Credits @@ -40,10 +44,16 @@ // Adds Autoload Classes $wgAutoloadClasses['PrefStatsHooks'] = dirname( __FILE__ ) . '/PrefStats.hooks.php'; +$wgAutoloadClasses['SpecialPrefStats'] = + dirname( __FILE__ ). '/SpecialPrefStats.php'; +$wgSpecialPages['PrefStats'] = 'SpecialPrefStats'; + // Adds Internationalized Messages $wgExtensionMessagesFiles['PrefStats'] = dirname( __FILE__ ) . '/PrefStats.i18n.php'; +$wgExtensionAliasesFiles['PrefStats'] = + dirname( __FILE__ ). '/PrefStats.alias.php'; // Registers Hooks $wgHooks['LoadExtensionSchemaUpdates'][] = 'PrefStatsHooks::schema'; Modified: trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.sql =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.sql 2009-06-15 21:21:25 UTC (rev 51931) +++ trunk/extensions/UsabilityInitiative/PrefStats/PrefStats.sql 2009-06-15 21:28:58 UTC (rev 51932) @@ -2,14 +2,14 @@ -- Schema for PrefStats -- -CREATE TABLE IF NOT EXISTS prefstats ( +CREATE TABLE IF NOT EXISTS /*_*/prefstats ( ps_user int NOT NULL, ps_pref varbinary(32) NOT NULL, ps_value blob NOT NULL, ps_start binary(14) NOT NULL, ps_end binary(14) NULL, - ps_duration unsigned int NOT NULL, -); + ps_duration int unsigned +) /*$wgDBTableOptions*/; -CREATE UNIQUE INDEX ps_user_pref ON prefstats (ps_user, ps_pref); -CREATE INDEX ps_duration_start ON prefstats (ps_duration, ps_start); +CREATE UNIQUE INDEX /*i*/ps_user_pref_start ON /*_*/prefstats (ps_user, ps_pref, ps_start); +CREATE INDEX /*i*/ps_duration_start ON /*_*/prefstats (ps_duration, ps_start); Added: trunk/extensions/UsabilityInitiative/PrefStats/Prefstats.alias.php =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/Prefstats.alias.php (rev 0) +++ trunk/extensions/UsabilityInitiative/PrefStats/Prefstats.alias.php 2009-06-15 21:28:58 UTC (rev 51932) @@ -0,0 +1,13 @@ +<?php +/** + * Special page aliases for Usability Initiative PrefStats extension + * + * @file + * @ingroup Extensions + */ + + $aliases = array(); + + $aliases['en'] = array( + 'PrefStats' => array( 'PrefStats' ), +); Property changes on: trunk/extensions/UsabilityInitiative/PrefStats/Prefstats.alias.php ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/extensions/UsabilityInitiative/PrefStats/SpecialPrefStats.php =================================================================== --- trunk/extensions/UsabilityInitiative/PrefStats/SpecialPrefStats.php (rev 0) +++ trunk/extensions/UsabilityInitiative/PrefStats/SpecialPrefStats.php 2009-06-15 21:28:58 UTC (rev 51932) @@ -0,0 +1,131 @@ +<?php +/** + * Special:PrefStats + * + * @file + * @ingroup Extensions + */ + +class SpecialPrefStats extends SpecialPage { + function __construct() { + parent::__construct( 'PrefStats', 'prefstats' ); + wfLoadExtensionMessages( 'PrefStats' ); + } + + function execute( $par ) { + global $wgRequest, $wgOut, $wgUser, $wgPrefStatsTrackPrefs; + $this->setHeaders(); + + // Check permissions + if ( !$this->userCanExecute( $wgUser ) ) { + $this->displayRestrictionError(); + return; + } + + $wgOut->setPageTitle( wfMsg( 'prefstats-title' ) ); + + if( !isset( $wgPrefStatsTrackPrefs[$par] ) ) { + $this->displayTrackedPrefs(); + return; + } + + $this->displayPrefStats( $par ); + } + + function displayTrackedPrefs() { + global $wgOut, $wgUser, $wgPrefStatsTrackPrefs; + $wgOut->addWikitext( wfMsg( 'prefstats-list-intro' ) ); + $wgOut->addHTML( Xml::openElement( 'ul' ) ); + foreach ( $wgPrefStatsTrackPrefs as $pref => $value ) { + $wgOut->addHTML( Xml::tags( 'li', array(), + $wgUser->getSkin()->link( + $this->getTitle( $pref ), + wfMsg( 'prefstats-list-elem', $pref, + $value ) ) ) ); + } + $wgOut->addHTML( Xml::closeElement( 'ul' ) ); + } + + function displayPrefStats( $pref ) { + global $wgOut, $wgUser, $wgRequest, $wgPrefStatsTrackPrefs; + $max = $this->getMaxDuration( $pref ); + $wgOut->addHTML( Xml::openElement( 'ul' ) ); + $stats = $this->getPrefStats( $pref, + $wgRequest->getIntOrNull( 'inc' ) ); + foreach ( $stats as $key => $val ) { + list( $from, $to ) = explode( '-', $key ); + $wgOut->addHTML( Xml::element( 'li', array(), + wfMsg( 'prefstats-stat-line', $val, $from, $to ) + ) ); + } + $wgOut->addHTML( Xml::closeElement( 'ul' ) ); + $wgOut->addHTML( Xml::element( 'img', array( 'src' => + $this->getGoogleChartParams( $stats ) ) ) ); + } + + function getGoogleChartParams( $stats ) { + global $wgPrefStatsChartDimensions; + return "http://chart.apis.google.com/chart?" . wfArrayToCGI( + array( + 'chs' => $wgPrefStatsChartDimensions, + 'cht' => 'bvs', + 'chds' => '0,' . max( $stats ), + 'chd' => 't:' . implode( ',', $stats ), + 'chxt' => 'x,y', + 'chxr' => '1,' . min( $stats ) . ',' . max( $stats ), + 'chxl' => '0:|'. implode( '|', array_keys( $stats ) ), + 'chm' => 'N*f0zy*,000000,0,-1,11' + ) ); + } + + function getPrefStats( $pref, $inc = null ) { + global $wgPrefStatsTimeUnit; + $max = ceil( $this->getMaxDuration( $pref ) / + $wgPrefStatsTimeUnit ); + $inc = max( 1, ( is_null( $inc ) ? ceil( $max / 10 ) : $inc ) ); + $retval = array(); + for( $i = 0; $i <= $max; $i += $inc ) { + $end = min( $max, $i + $inc ); + $key = $i . '-' . $end; + $retval[$key] = $this->countBetween( $pref, + $i * $wgPrefStatsTimeUnit, + $end * $wgPrefStatsTimeUnit ); + } + return $retval; + } + + /** + * Get the highest duration in the database + */ + function getMaxDuration( $pref ) { + $dbr = wfGetDb( DB_SLAVE ); + $max1 = $dbr->selectField( 'prefstats', 'MAX(ps_duration)', + array( 'ps_pref' => $pref ), __METHOD__ ); + $minTS = $dbr->selectField( 'prefstats', 'MIN(ps_start)', + array( 'ps_pref' => $pref, + 'ps_duration IS NULL' ), __METHOD__ ); + $max2 = wfTimestamp( TS_UNIX ) - wfTimestamp( TS_UNIX, $minTS ); + return max( $max1, $max2 ); + } + + /** + * Count the number of users having $pref enabled between + * $min and $max seconds + */ + function countBetween( $pref, $min, $max ) { + $dbr = wfGetDb( DB_SLAVE ); + $count1 = $dbr->selectField( 'prefstats', 'COUNT(*)', array( + 'ps_pref' => $pref, + 'ps_duration < ' . intval( $max ), + 'ps_duration >= ' . intval( $min ) + ), __METHOD__ ); + $maxTS = wfTimestamp( TS_UNIX ) - $min; + $minTS = wfTimestamp( TS_UNIX ) - $max; + $count2 = $dbr->selectField( 'prefstats', 'COUNT(*)', array( + 'ps_duration IS NULL', + 'ps_start <' . $dbr->timestamp( $maxTS ), + 'ps_start >=' . $dbr->timestamp( $minTS ) + ), __METHOD__ ); + return $count1 + $count2; + } +} Property changes on: trunk/extensions/UsabilityInitiative/PrefStats/SpecialPrefStats.php ___________________________________________________________________ Added: svn:eol-style + native _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs