r55425 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r55424‎ | r55425 | r55426 >
Date:19:50, 21 August 2009
Author:nimishg
Status:deferred
Tags:
Comment:
JS click tracking!
- Extension to track user clicks
- table to track user daily contributions
Modified paths:
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php (added) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.hooks.php (modified) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.i18n.php (added) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.js (added) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php (modified) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.sql (modified) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/ClickTrackingEvents.sql (added) (history)
  • /trunk/extensions/UsabilityInitiative/ClickTracking/UserDailyContribs.sql (added) (history)

Diff [purge]

Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.hooks.php
@@ -10,6 +10,10 @@
1111 class ClickTrackingHooks {
1212
1313 /* Static Functions */
 14+
 15+ /* initializations */
 16+
 17+ /* 3 tables for click tracking */
1418 public static function schema() {
1519 global $wgExtNewTables;
1620
@@ -18,28 +22,156 @@
1923 dirname( __FILE__ ) . '/ClickTracking.sql'
2024 );
2125
 26+ $wgExtNewTables[] = array(
 27+ 'user_daily_contribs',
 28+ dirname( __FILE__ ) . '/UserDailyContribs.sql'
 29+ );
 30+
 31+ $wgExtNewTables[] = array(
 32+ 'click_tracking_events',
 33+ dirname( __FILE__ ) . '/ClickTrackingEvents.sql'
 34+ );
 35+
2236 return true;
2337 }
2438
 39+
2540 /**
 41+ * adds javascript
 42+ */
 43+ public static function addJS(){
 44+ UsabilityInitiativeHooks::initialize();
 45+ UsabilityInitiativeHooks::addScript('ClickTracking/ClickTracking.js');
 46+ UsabilityInitiativeHooks::addVariables(array(
 47+ 'wgEditId' => ClickTrackingHooks::get_session_id()
 48+ ));
 49+ return true;
 50+ }
 51+
 52+
 53+ /**
 54+ * Gets the session ID...we just want a unique random ID for the page load
 55+ * @return session ID
 56+ */
 57+ public static function get_session_id(){
 58+ global $wgUser;
 59+ return wfGenerateToken(array($wgUser->getName(), time()));
 60+ }
 61+
 62+ /**
 63+ * Get the number of revisions a user has made since a given time
 64+ * @param $ts beginning timestamp
 65+ * @return number of revsions this user has made
 66+ */
 67+ public static function getEditCountSince($ts){
 68+ global $wgUser;
 69+
 70+ //convert to just the day
 71+ $time = gmdate('Ymd', wfTimestamp(TS_UNIX,$ts));
 72+
 73+ $dbr = wfGetDB( DB_SLAVE );
 74+
 75+ $edits = $dbr->selectField(
 76+ 'user_daily_contribs',
 77+ 'SUM(contribs)',
 78+ array(
 79+ 'user_id' => $wgUser->getId(),
 80+ "day < '$time'"
 81+ ),
 82+ __METHOD__
 83+ );
 84+
 85+ //user hasn't made any edits in whatever amount of time
 86+ if( $edits == null ){
 87+ $edits = 0;
 88+ }
 89+
 90+ return $edits;
 91+
 92+ }
 93+
 94+ /**
 95+ * Stores a new contribution
 96+ * @return unknown_type
 97+ */
 98+ public static function storeNewContrib(){
 99+ global $wgUser;
 100+ $today = gmdate('Ymd',time());
 101+ $dbw = wfGetDB( DB_MASTER );
 102+ $sql =
 103+ "INSERT INTO user_daily_contribs (user_id,day,contribs) VALUES ({$wgUser->getId()},$today,1) ON DUPLICATE KEY UPDATE contribs=contribs+1;";
 104+ $dbw->query($sql, __METHOD__);
 105+ return true;
 106+ }
 107+
 108+ /**
 109+ * get event ID from name
 110+ * @param $event_name
 111+ * @return $event ID
 112+ */
 113+ public static function getEventIDFromName($event_name){
 114+ $dbr = wfGetDB( DB_SLAVE );
 115+
 116+ $id_num = $dbr->selectField(
 117+ 'click_tracking_events',
 118+ 'id',
 119+ array(
 120+ 'event_name' => $event_name
 121+ ),
 122+ __METHOD__
 123+ );
 124+
 125+ // if this entry doesn't exist...
 126+ // this will be incredibly rare as the whole database will only have a few hundred entries in it at most
 127+ // and getting DB_MASTER up top would be wasteful
 128+
 129+ if($id_num === false){
 130+ $dbw = wfGetDB( DB_MASTER );
 131+ $dbw->insert('click_tracking_events',
 132+ array('event_name' => (string) $event_name),
 133+ __METHOD__);
 134+
 135+ //should be inserted now...if not, we return zero later
 136+
 137+ $id_num = $dbr->selectField(
 138+ 'click_tracking_events',
 139+ 'id',
 140+ array(
 141+ 'event_name' => $event_name
 142+ ),
 143+ __METHOD__
 144+ );
 145+ }
 146+
 147+ if($id_num === false){ return 0;}
 148+ return $id_num;
 149+ }
 150+
 151+ /**
26152 * Track particular event
 153+ * @param $session_id unique session id for this editing sesion
27154 * @param $is_logged_in whether or not the user is logged in
28155 * @param $namespace namespace the user is editing
29156 * @param $event_id event type
30157 * @param $contribs contributions the user has made (or NULL if user not logged in)
 158+ * @param $contribs_in_timespan number of contributions user has made in a given timespan
31159 * @return true if the event was stored in the DB
32160 */
33 - public static function trackEvent( $is_logged_in, $namespace, $event_id, $contribs = 0 ){
 161+ public static function trackEvent( $session_id, $is_logged_in, $namespace, $event_id, $contribs=0, $contribs_in_timespan=0 ){
 162+
34163 $dbw = wfGetDB( DB_MASTER );
35164
36165 $dbw->begin();
37 -
 166+
38167 // Builds insert information
39168 $data = array(
 169+ 'session_id' => (string) $session_id,
40170 'is_logged_in' => (bool) $is_logged_in,
41 - 'namespace' => (int) $namespace,
42 - 'event_id' => (int) $event_id,
43 - 'user_contribs' => ( $is_logged_in? $contribs : null )
 171+ 'user_total_contribs' => ( $is_logged_in ? (int) $contribs : null ),
 172+ 'user_contribs_span' => ( $is_logged_in ? (int) $contribs_in_timespan : null ),
 173+ 'namespace' => (int) $namespace,
 174+ 'event_id' => (int) $event_id
 175+
44176 );
45177
46178 $db_status = $dbw->insert('click_tracking', $data, __METHOD__);
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.js
@@ -0,0 +1,11 @@
 2+
 3+(function($) {
 4+
 5+ // creates 'track action' function to call the clicktracking API and send the ID
 6+$.trackAction = function ( id ){
 7+ $j.post( wgScriptPath + '/api.php', { 'action': 'clicktracking', 'eventid': id, 'editid': wgEditId } );
 8+};
 9+
 10+return $(this);
 11+
 12+})(jQuery);
Property changes on: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.js
___________________________________________________________________
Name: svn:eol-style
113 + native
Index: trunk/extensions/UsabilityInitiative/ClickTracking/UserDailyContribs.sql
@@ -0,0 +1,21 @@
 2+--
 3+-- Schema for UserDailyContribs
 4+--
 5+-- Used in clicktracking to determine how active the user is
 6+--
 7+
 8+CREATE TABLE IF NOT EXISTS /*_*/user_daily_contribs (
 9+
 10+ -- user id
 11+ user_id integer NOT NULL default 0,
 12+
 13+ -- day
 14+ day DATE NOT NULL,
 15+
 16+ -- contributions on that day by that user
 17+ contribs integer NOT NULL default 0,
 18+
 19+ -- a unique entry for a given user_id and day
 20+ PRIMARY KEY(user_id, day)
 21+
 22+) /*$wgDBTableOptions*/;
Property changes on: trunk/extensions/UsabilityInitiative/ClickTracking/UserDailyContribs.sql
___________________________________________________________________
Name: svn:eol-style
123 + native
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.sql
@@ -5,17 +5,23 @@
66 CREATE TABLE IF NOT EXISTS /*_*/click_tracking (
77 -- Timestamp
88 action_time timestamp NOT NULL default CURRENT_TIMESTAMP,
9 -
 9+
 10+ -- session id
 11+ session_id varbinary(255) NOT NULL,
 12+
1013 --true if the user is logged in
1114 is_logged_in boolean NOT NULL,
1215
13 - -- contributions
14 - user_contribs integer,
 16+ -- total user contributions
 17+ user_total_contribs integer,
1518
 19+ -- user contributions over a specified timespan
 20+ user_contribs_span integer,
 21+
1622 -- namespace being edited
1723 namespace integer NOT NULL,
1824
1925 -- event ID (not unique)
2026 event_id integer NOT NULL
21 -
 27+
2228 ) /*$wgDBTableOptions*/;
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php
@@ -0,0 +1,86 @@
 2+<?php
 3+
 4+/**
 5+ * Extend the API for click tracking
 6+ *
 7+ * @author nimishgautam
 8+ *
 9+ */
 10+class ApiClickTracking extends ApiBase {
 11+
 12+ /**
 13+ * runs when the api is called with "clicktracking", takes in "eventid" and an edit token given to the user, "editid"
 14+ * @see includes/api/ApiBase#execute()
 15+ */
 16+ public function execute(){
 17+ global $wgUser, $wgTitle;
 18+
 19+ $params = $this->extractRequestParams();
 20+ $this->validateParams( $params );
 21+ $eventid_to_lookup = $params['eventid'];
 22+ $session_id = $params['editid'];
 23+
 24+ //Event ID lookup table
 25+ $event_id = ClickTrackingHooks::getEventIDFromName(urldecode($eventid_to_lookup));
 26+
 27+ $is_logged_in = $wgUser->isLoggedIn();
 28+
 29+
 30+ ClickTrackingHooks::trackEvent(
 31+ $session_id, //randomly generated session ID
 32+ $is_logged_in, //is the user logged in?
 33+ $wgTitle->getNamespace(), //what namespace are they editing?
 34+ $event_id, //event ID passed in
 35+ ( $is_logged_in ? $wgUser->getEditCount() : 0 ), //total edit count or 0 if anonymous
 36+ ( $is_logged_in ?
 37+ ( ClickTrackingHooks::getEditCountSince( time() - $wgClickTrackContribTimeValue) )
 38+ : 0) //contributions since whatever the time value is, or 0 if anonymous
 39+ );
 40+ }
 41+
 42+ /**
 43+ * required parameter check
 44+ * @param $params params extracted from the POST
 45+ * @return unknown_type
 46+ */
 47+ protected function validateParams( $params ) {
 48+ $required = array( 'eventid', 'editid');
 49+ foreach( $required as $arg ) {
 50+ if ( !isset( $params[$arg] ) ) {
 51+ $this->dieUsageMsg( array( 'missingparam', $arg ) );
 52+ }
 53+ }
 54+ }
 55+
 56+
 57+
 58+ public function getParamDescription() {
 59+ return array(
 60+ 'eventid' => 'string of eventID',
 61+ 'editid' => 'unique edit ID for this edit session'
 62+ );
 63+ }
 64+
 65+ public function getDescription() {
 66+ return array(
 67+ 'Track user clicks on Javascript items.' );
 68+ }
 69+
 70+ public function getAllowedParams() {
 71+ return array(
 72+ 'eventid' => array(
 73+ ApiBase::PARAM_TYPE => 'string'
 74+ ),
 75+ 'editid' => array(
 76+ ApiBase::PARAM_TYPE => 'string'
 77+ )
 78+ );
 79+ }
 80+
 81+ //TODO: create a more useful 'version number'
 82+ public function getVersion() {
 83+ return __CLASS__ . ': $Id: $';
 84+ }
 85+
 86+
 87+}
\ No newline at end of file
Property changes on: trunk/extensions/UsabilityInitiative/ClickTracking/ApiClickTracking.php
___________________________________________________________________
Name: svn:eol-style
188 + native
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTrackingEvents.sql
@@ -0,0 +1,18 @@
 2+--
 3+-- Schema for ClickTrackingEvents
 4+--
 5+-- Used to keep track of the various click events by ID
 6+--
 7+
 8+CREATE TABLE IF NOT EXISTS /*_*/click_tracking_events (
 9+
 10+ -- event name
 11+ event_name VARBINARY(255) unique,
 12+
 13+ -- day
 14+ id INTEGER AUTO_INCREMENT,
 15+
 16+ -- keyed on event, sql makes you use the id as a primary key
 17+ PRIMARY KEY(id)
 18+
 19+) /*$wgDBTableOptions*/;
Property changes on: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTrackingEvents.sql
___________________________________________________________________
Name: svn:eol-style
120 + native
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.i18n.php
@@ -0,0 +1,17 @@
 2+<?php
 3+/**
 4+ * Internationalisation for Usability Initiative Click Tracking extension
 5+ *
 6+ * @file
 7+ * @ingroup Extensions
 8+ */
 9+
 10+$messages = array();
 11+
 12+/** English
 13+ * @author Nimish Gautam
 14+ */
 15+$messages['en'] = array(
 16+ 'clicktracking' => 'Usability Initiative click tracking',
 17+ 'clicktracking-desc' => 'Click tracking, intended for tracking events that do not cause a page refresh'
 18+);
\ No newline at end of file
Property changes on: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.i18n.php
___________________________________________________________________
Name: svn:eol-style
119 + native
Index: trunk/extensions/UsabilityInitiative/ClickTracking/ClickTracking.php
@@ -21,12 +21,17 @@
2222 //functions should check if this is set before logging clicktrack events
2323 $wgClickTrackEnabled = true;
2424
 25+
 26+//set the time window for what we consider 'recent' contributions, in days
 27+$wgClickTrackContribTimeValue = 60 * 60 * 24 * 365 / 2; //half a year
 28+
2529 // Credits
2630 $wgExtensionCredits['other'][] = array(
2731 'path' => __FILE__,
2832 'name' => 'Click Tracking',
2933 'author' => 'Nimish Gautam',
3034 'version' => '0.1.1',
 35+ 'descriptionmsg' => 'clicktracking-desc',
3136 'url' => 'http://www.mediawiki.org/wiki/Extension:UsabilityInitiative'
3237 );
3338
@@ -37,4 +42,12 @@
3843 $wgAutoloadClasses['ClickTrackingHooks'] =
3944 dirname( __FILE__ ) . '/ClickTracking.hooks.php';
4045
 46+$wgAutoloadClasses['ApiClickTracking'] = dirname( __FILE__ ) . '/ApiClickTracking.php';
 47+
4148 $wgHooks['LoadExtensionSchemaUpdates'][] = 'ClickTrackingHooks::schema';
 49+
 50+$wgHooks['ArticleSaveComplete'][] = 'ClickTrackingHooks::storeNewContrib';
 51+
 52+$wgAPIModules['clicktracking'] = 'ApiClickTracking';
 53+
 54+$wgHooks['EditPage::showEditForm:initial'] [] = 'ClickTrackingHooks::addJS';

Follow-up revisions

RevisionCommit summaryAuthorDate
r55427Follow-up r55425: Add clicktracking to translatewikiraymond20:15, 21 August 2009
r55430follow-up to r55425:...ashley20:28, 21 August 2009

Status & tagging log