Extension:UserPageViewTracker

From MediaWiki.org

Jump to: navigation, search
Manual on MediaWiki Extensions
List of MediaWiki Extensions
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

ParserAfterTidy

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

  1. Execute the SQL scripts below to create the table and view needed by the extension. Make sure to set the appropriate prefix.
  2. Copy & paste the PHP code below into a new file called "UserPageViewTracker.php" located in your extensions directory.
  3. 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 .= '&nbsp;</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 .="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
                $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;

[edit] See also

Personal tools