Extension:UserPageViewTracker
From MediaWiki.org
|
UserPageViewTracker Release status: beta |
|
|---|---|
| Implementation | Page action, Special page, Database |
| Description | Tracks user page hits |
| Author(s) | Kimon Andreou (Kimon Talk) |
| Version | 1.0.0.1 (2007-11-07) |
| MediaWiki | Tested on 1.10 |
| License | GPL |
| Download | See below |
| Added rights | userpagehits |
| Hooks used | |
Contents |
[edit] Description
This extension allows users who have the right "userpagehits" to track usage of the site. It will display the pages visited per users, # of visits, and last visit.
Every time a user visits a page, a table in the database gets updated with the hit count for the user on that page. In other words, for every page & user combination, there is a hitcount.
The special page displays this information and allows the filtering of users to either include only or exclude. A list of users can be provided by using the pipe symbol (|) as a delimiter.
[edit] Installation
- Execute the SQL scripts below to create the table and view needed by the extension. Make sure to set the appropriate prefix.
- Copy & paste the PHP code below into a new file called "UserPageViewTracker.php" located in your extensions directory.
- Add the lines to the end of your LocalSettings.php file:
require_once( "$IP/extensions/UserPageViewTracker.php" ); $wgGroupPermissions['userpagehits']['userpagehits'] = true; $wgGroupPermissions['sysop' ]['userpagehits'] = true;
You will now have a new security group called "userpagehits" you can assign users to.
[edit] Source
[edit] UserPageViewTracker.php
<?php # The UserPageViewTracker extension, an extension for providing a view into user activity # @addtogroup Extensions # @author Kimon Andreou # @copyright © 2007 by Kimon Andreou # @licence GNU General Public Licence 2.0 or later if ( !defined( 'MEDIAWIKI' ) ) { die( 'This file is a MediaWiki extension, it is not a valid entry point' ); } #credit the extension $wgExtensionCredits['parserhook'][] = array( 'name'=>'User Page View Tracker', 'url'=>'http://www.mediawiki.org/wiki/Extension:UserPageViewTracker', 'author'=>'Kimon Andreou', 'description'=>'Tracks page views by user', ); #register with a hook $wgHooks['ParserAfterTidy'][] = 'wfUserPageViewTracker'; #function that updates the table containing the hits function wfUserPageViewTracker(&$parser, &$text) { global $wgDBprefix, $wgDBname, $wgUser, $wgOut; $wgOut->enableClientCache(false); $wgOut->addMeta("http:Pragma", "no-cache"); $title = $parser->getTitle(); $artID = $title->getArticleID(); $db = &wfGetDB(DB_SLAVE); #check to see if the user has visited this page before $query = "SELECT hits, last FROM ".$wgDBprefix."user_page_views WHERE user_id = ".$wgUser->getID(); $query .= " AND page_id = $artID"; if($result = $db->doQuery($query)) { $row = $db->fetchRow($result); $last = $row["last"]; #due to multiple calls, don't double count if we've been here within the last 5 seconds if($last < (wfTimestampNow() - 5)) { $hits = $row["hits"]; if($hits > 0) { $query = "UPDATE ".$wgDBprefix."user_page_views "; $query .= "SET hits = ".($hits + 1); $query .= ", last='".wfTimestampNow()."'"; $query .= " WHERE user_id = ".$wgUser->getID(); $query .= " AND page_id = ".$artID; } else { #looks like this is our first visit, create the record $query = "INSERT INTO ".$wgDBprefix."user_page_views(user_id, page_id, hits, last)"; $query .= " VALUES(".$wgUser->getID().",".$artID.",1,'".wfTimestampNow()."')"; } $db->doQuery($query); } } return true; } ################################################################### ### ### ### Special page section ### ### ################################################################### $wgSpecialPages['SpecialUserpagehits'] = 'SpecialUserpagehits'; $wgExtensionCredits['specialpage'][] = array( 'name' => 'User Page Hits', 'description' => 'Displays the user hits per page', 'url' => 'http://www.mediawiki.org/wiki/Extension:UserPageViewTracker', 'author' => 'Kimon Andreou'); #bring in the specialpage stuff require_once("$IP/includes/SpecialPage.php"); #our special page class class SpecialUserpagehits extends SpecialPage { #constructor function SpecialUserpagehits() { global $wgMessageCache; $wgMessageCache->addMessage('specialuserpagehits', 'User page hits'); $wgMessageCache->addMessage('userpagehits', 'User page hits'); SpecialPage::SpecialPage('SpecialUserpagehits', 'userpagehits'); } #do your stuff function execute( $par = null ) { global $wgRequest, $wgOut; $wgOut->setPageTitle('User page hits'); list( $limit, $offset ) = wfCheckLimits(); $userTarget = isset($par) ? $par : $wgRequest->getVal( 'username' ); $up = new UserPageHitsPager($user); # getBody() first to check, if empty $usersbody = $up->getBody(); $s = $up->getPageHeader(); if( $usersbody ) { $s .= $up->getNavigationBar(); $s .= '<table class="wikitable" width="100%" cellspacing="0" cellpadding="0">'; $s .= '<tr><th>#</th><th>User Name</th><th>Real Name</th><th>Page</th><th>Hits</th>'; $s .= '<th>Last</th></tr>'; $s .= $usersbody . '</table>'; $s .= $up->getNavigationBar() ; } else { $s .= '<p>' . wfMsgHTML('listusers-noresult') . '</p>'; }; $wgOut->addHTML( $s ); } } require_once("$IP/includes/Pager.php"); #create a custom pager class UserPageHitsPager extends AlphabeticPager { protected $rowCount = 0; function __construct($username=null) { global $wgRequest; $this->filterUsers = $filterUsers != "" ? $filterUsers : $wgRequest->getVal( 'filterusers' ); $this->filterUserList = explode("|", $this->filterUsers); $this->ignoreUsers = $ignoreUsers != "" ? $ignoreUsers : $wgRequest->getVal( 'ignoreusers' ); $this->ignoreUserList = explode("|", $this->ignoreUsers); parent::__construct(); } function getIndexField() { return "rownum"; } function getQueryInfo() { list ($userpagehits) = wfGetDB()->tableNamesN('user_page_hits'); $conds = array(); if($this->filterUsers) { $includeUsers = "user_name in ( '"; $includeUsers .= implode("', '", $this->filterUserList)."')"; $conds[] = $includeUsers; #$conds[] = "user_name = ".wfGetDB()->addQuotes($this->requestedUser); } if($this->ignoreUsers) { $excludeUsers = "user_name not in ( '"; $excludeUsers .= implode("', '", $this->ignoreUserList)."')"; $conds[] = $excludeUsers; } $table = "(select @rownum:=@rownum+1 as rownum,"; $table .= "user_name, user_real_name, page_namespace, page_title,hits, last "; $table .= "from (select @rownum:=0) r, "; $table .= "(select user_name, user_real_name, page_namespace, page_title,hits,"; $table .= "last from user_page_hits) p) results"; return array( 'tables' => " $table ", 'fields' => array( 'rownum', 'user_name', 'user_real_name', 'page_namespace', 'page_title', 'hits', "concat(substr(last, 1, 4),'-',substr(last,5,2),'-',substr(last,7,2),' ',substr(last,9,2),':',substr(last,11,2),':',substr(last,13,2)) AS last"), 'conds' => $conds ); } function formatRow( $row ) { $userPage = Title::makeTitle( NS_USER, $row->user_name ); $name = $this->getSkin()->makeLinkObj( $userPage, htmlspecialchars( $userPage->getText() ) ); $pageTitle = Title::makeTitle( $row->page_namespace, $row->page_title ); if($row->page_namespace > 0) { $pageFullName = $pageTitle->getNsText().":".htmlspecialchars($pageTitle->getText() ); } else { $pageFullName = htmlspecialchars( $pageTitle->getText()); } $page = $this->getSkin()->makeLinkObj( $pageTitle, $pageFullName ); $this->rowCount += 1; $res = '<tr>'; $res .= "<td style=\"text-align:center\">$this->rowCount</td>"; $res .= '<td>'.$name.'</td><td>'; if ($row->user_real_name) { $res .= $row->user_real_name.'</td><td>'; } else { $res .= ' </td><td>'; } $res .= "$page</td>"; $res .= "<td style=\"text-align:right\">$row->hits</td>"; $res .= "<td style=\"text-align:center\">$row->last</td>"; $res .= "</tr>\n"; return $res; } function getBody() { if (!$this->mQueryDone) { $this->doQuery(); } $batch = new LinkBatch; $db = $this->mDb; $this->mResult->rewind(); $this->rowCount = 0; while ( $row = $this->mResult->fetchObject() ) { $batch->addObj( Title::makeTitleSafe( NS_USER, $row->user_name ) ); } $batch->execute(); $this->mResult->rewind(); return parent::getBody(); } #this is where we set up the form at the top of the special page to be able to set filters function getPageHeader() { $out = "<form name=\"filteruser\" id=\"filteruser\" method=\"post\">\n"; $out .="Usernames: <input type=\"text\" name=\"filterusers\" value=\"".$this->filterUsers."\">"; $out .="<input type=\"submit\" value=\"Filter\">"; $out .=" "; $out .="Usernames: <input type=\"text\" name=\"ignoreusers\" value=\"".$this->ignoreUsers."\">"; $out .="<input type=\"submit\" value=\"Exclude\">"; $out .="</form>\n<hr>\n"; return $out; } /** * Preserve filter offset parameters when paging * @return array */ function getDefaultQuery() { $query = parent::getDefaultQuery(); if( $this->filterUsers != '' ) $query['filterusers'] = $this->filterUsers; if( $this->ignoreUsers != '' ) $query['ignoreusers'] = $this->ignoreUsers; return $query; } }
[edit] UserPageViews.sql
CREATE TABLE `user_page_views` ( `user_id` int(5) UNSIGNED NOT NULL, `page_id` int(8) UNSIGNED NOT NULL, `hits` int(10) UNSIGNED NOT NULL, `last` char(14) DEFAULT NULL, PRIMARY KEY (`user_id`,`page_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
[edit] UserPageHits.sql
CREATE VIEW `user_page_hits` AS SELECT `u`.`user_name` AS `user_name`, `u`.`user_real_name` AS `user_real_name`, `p`.`page_namespace` AS `page_namespace`, `p`.`page_title` AS `page_title`, `v`.`hits` AS `hits`, `v`.`last` AS `last` FROM ((`user` `u` JOIN `page` `p`) JOIN `user_page_views` `v`) WHERE ((`u`.`user_id` = `v`.`user_id`) AND (`p`.`page_id` = `v`.`page_id`)) ORDER BY `u`.`user_id`,`v`.`hits` DESC;

