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

Reply via email to