Dokuwiki - View Counter

counter.jpg This adds a simple counter for your Dokuwiki pages. The visits are stored in /wiki/data/.cache/<wiki_id>.visits.

Changes: (dokuwiki-2005-05-07)

  • inc/template.php
    • same as above but the function is named tpl_pageinfo()

Changes: (dokuwiki-2005-06-11)

  1. create a directory _views in datadir (usually data) and copy your old visits file in there
  2. create the file inc/counter.php
    <?php
    global $ID,$ACT;
     
    $file=realpath($conf['datadir']).'/_views/'.$ID;
     
    if (file_exists($file)) {
      $views=FALSE;
      while ($views===FALSE) {
        $views=file_get_contents($file);
        if ($views===FALSE) {
          usleep(50000);
        }
      }
      $views=$views+1;
    } else {
      $views=1;
    }
     
    if (($ACT == 'show') && ($INFO['exists'])) {
      while(!$written) {
        $written=file_put_contents($file,$views);
        if (!$written) {
          usleep(50000);
        }
      }
    }
     
    $fn.=" ($views views) ";
  3. add include('counter.php'); in inc/template.php as below
    function tpl_pageinfo(){
      global $conf;
      global $lang;
      global $INFO;
      global $REV;
     
      // prepare date and path
      $fn = $INFO['filepath'];
      if(!$conf['fullpath']){
        if($REV){
          $fn = str_replace(realpath($conf['olddir']).DIRECTORY_SEPARATOR,'',$fn);
        }else{
          $fn = str_replace(realpath($conf['datadir']).DIRECTORY_SEPARATOR,'',$fn);
        }
      }
      $fn = utf8_decodeFN($fn);
      $date = date($conf['dformat'],$INFO['lastmod']);
     
      include('counter.php');

Comments

Are their plans afoot to update this for DW 09-03-2006?

N. (14 MAR '06)

His revision marked dokuwiki-2005-07-13 works in DokuWiki 2006-03-09 – Z. (2006-05-19)

It works like a charm on my wiki. Once I installed it, I was suprised to see how busy my wiki really is. - Christopher Wellons (mosquitopsu – gmail)


On windows systems one have to adjust the path separators to back slashes:

$fp_views=fopen(realpath($conf['datadir'])."\_cache\$ID.visits",'a+');

Daniel

But in windows with IIS that's not necesary

GCH ;) dic 2007


In the instructions, I think the directory should be /data/pages/_views/

Other versions

New in this version:

  • support for file_put_contents in php4
  • infinite loop check
  • code clean up
  • tested in dokuwiki 2006-11-06 on CentOS 4.3 and Debian
  • more info in: Linux.org.py wiki

Instructions:

  • create the directory /dokuwiki/data/pages/_views
  • make sure /dokuwiki/data/pages/_views is owned by the webserver user
    chown apache.apache -R /dokuwiki/data/pages/_views
  • create the file /dokuwiki/inc/counter.php and put this code in there:
    <?php
     
    /* 
     * simulating file_put_contents() from PHP5
     * for PHP 4.3.9 (Centos 4.3)
     * http://tinymailto.com/oliver
     */
    function file_put_contents_counter($file, $views) {
      $written = false;
      if( $fp_counter = fopen($file, 'w') ) {
        // lock before writting
        if (flock($fp_counter, LOCK_EX)) { 
          $written = fwrite($fp_counter, $views);
          flock($fp_counter, LOCK_UN);
        }
        fclose($fp_counter);
      }
      if($written === FALSE) {
        return 0;
      }
      else {
        return $written;
      }
    }
     
    global $ID,$ACT;
     
    // local variables
    $file = "";
    $views = false;
    $read_tries = 3;
    $read_count = 0;
    $written=0;
    $write_tries = 3;
    $write_count = 0;
     
    $file=realpath($conf['datadir']).'/_views/'.$ID;
     
    if (file_exists($file)) {
      while ($views===FALSE) {
        $views=file_get_contents($file);
        if ($views===FALSE) {
          usleep(50000);
        }
        $read_count++;
        if($read_count > $read_tries) {
          $views = 0;
          break;
        }
      }
      $views = intval($views) + 1;
    } else {
      $views=1;
    }
     
    if (($ACT == 'show') && ($INFO['exists'])) {
      while(!$written) {
        $written=file_put_contents_counter($file,$views);
        // for php5 use this line
        //$written=file_put_contents($file,$views);
        if (!$written) {
          usleep(50000);
        }
        $write_count++;
        if($write_count > $write_tries) {
          break;
        }
      }
    }
     
    $fn.=" ($views views) ";
  • edit /dokuwiki/inc/template.php to look like this:
      $fn = utf8_decodeFN($fn);
      $date = date($conf['dformat'],$INFO['lastmod']);
     
      // print it
      if($INFO['exists']){
        // counter
        include('counter.php');
        print $fn;

Comments

This plug in is great. I made a tweak to run it on Windows Server and IIS on line 37:

$file=realpath($conf['datadir']).'\\_views\\'.$ID;

Also if you use namespaces (e.g. usa:colorado:evergreen), the filename needs to be url-encoded to make it a legal file name:

# Windows:
$file=realpath($conf['datadir']).'\\_views\\'.urlencode($ID);
 
# Unix:
$file=realpath($conf['datadir']).'/_views/'.urlencode($ID);

Philippe Monnet - techarch at monnet-usa.com


An example of Page View Counter Stats

Just for the pleasure : make a page with all the page View in an table from the most view to the less view : just copy this code in page with php activated and change this : YOURSITEWEB.URL...

 
~~NOCACHE~~
 
<php>
 
 $dir = realpath($conf['datadir']).'/_views/';
$ii = 0;
 
 $Files = array();
 $It =  opendir($dir);
 if (! $It)
  die('Cannot list files for ' . $dir);
 while ($Filename = readdir($It))
 {
  if ($Filename == '.' || $Filename == '..')
   continue;
 
$handle = @fopen($dir.$Filename, "r");
if ($handle) {   
while (!feof($handle)) 
{     
 $buffer = fgets($handle, 4096);     
// echo $buffer."<br>";   
}   
fclose($handle);}
 
 
 
  $LastModified = filemtime($dir . $Filename);
    $Files[$ii] = array('fichier'=>$Filename, 'nbre'=>$buffer, 'dat'=>$LastModified);
$ii = $ii +1;
 }
 
 
 
 
 
   $sort_arr = array();
 foreach($Files AS $uniqid => $row){
        foreach($row AS $key=>$value){
            $sort_arr[$key][$uniqid] = $value;
        }
 
    }
 
 
array_multisort($sort_arr['nbre'], SORT_DESC,  $Files);
 
 
 
echo "<table><tr><td>Num</td><td>nombre</td><td>date</td><td>lien</td><td></tr>";
		for($i = 0; $i <= count($Files)-1;  $i++){
 
$lien = "<a href=\"YOURSITEWEB.URL/doku.php?id=".$Files[$i]['fichier']."\">".$Files[$i]['fichier']."</a>";
			echo "<tr><td>".$i."</td> <td>".$Files[$i]['nbre']."</td> <td>".date("d-m-Y",$Files[$i]['dat'])."</td> <td>".$lien."</td> </tr>";
 
	}
echo "</table>";
 
 
 
 
 
 
</php>

Count unique views for today

I patched the previos script because on my wiki I need to count unique views for today.
(Also I delete the PHP4 writing file support)

Instructions:

  • Create the directory wiki_dir/data/pages/_views
  • Make sure wiki_dir/data/pages/_views is owned by the webserver user:
chown -R www:www wiki_dir/data/pages/_views

(or change www:www on your server's uid and gid)

  • Create the file wiki_dir/inc/counter.php and put this code in there:
<?php
 
/* 
	http://tinymailto.com/oliver
 
	Patched by ASCHE. Count unique views for today.
	http://asche0.ath.cx
*/
 
###############################################
$today_str = "today"; // you can translate this =)
$views_str = "views";
###############################################

global $ID, $ACT;
 
$myip    = "<".$_SERVER["REMOTE_ADDR"].">";
$ips     = "";
$unique  = true;
$views   = 0;
$d       = date("Ymd");
 
$file = realpath($conf["datadir"])."/_views/".$ID;
 
if (file_exists($file)) {
    $content = file_get_contents($file);
	$pos = strpos($content, " ");
 
	if ($pos !== FALSE) {
		$views = substr($content, 0, $pos);
		$str   = substr($content, $pos + 1);
		$pos   = strpos($str, " ");
 
		if ($pos !== FALSE) {
			$old_d = substr($str, 0, $pos);
			$ips   = substr($str, $pos + 1);
 
			if ($old_d != $d) {
				$views = 0;
				$ips   = "";
			} else if (strpos($ips, $myip) !== FALSE) {
				$unique = false;
			}
		}
	}
}
 
if (($ACT == "show") && ($INFO["exists"]) && ($unique)) {
    $ips.="\n".$myip;
 
	$content = ++$views." ".$d." ".$ips;
	file_put_contents($file, $content);
}
 
$fn.=" ($today_str $views $views_str) ";
 
?>
  • Edit function tpl_pageinfo in wiki_dir/inc/template.php to look like this:
  $fn = utf8_decodeFN($fn);
  $date = strftime($conf['dformat'],$INFO['lastmod']);
 
  // print it
  if($INFO['exists']){
    ###############################################
    include("counter.php");
    ###############################################
    print $fn;

–ASCHE

Error

The page give me 2.133 errors saying this:

Warning: file_put_contents(C:\wamp\www\dokuwiki-2008-05-05\data\pages/_views/blog:blogs) [function.file-put-contents]: failed to open stream: Invalid argument in C:\wamp\www\dokuwiki-2008-05-05\inc\counter.php on line 21

What I do? ?::?::?::?::?::?::?::?:

The Solution

I had the same Problem. “counter.php” is not able to handle namespaces.

Replace following code:

$file=realpath($conf['datadir']).'/_views/'.$ID;

with this one:

$file=realpath($conf['datadir']).'/_views/'.str_replace(array("\\","/",":"),array("$","$","$"),$ID);

Error

Seeing similar problem as above, but with Unix, not windows in DokuWiki v.2008-05-05:

/auto/web-misc/wwwin/wiki/data/pages/multicast.txt Warning: fopen(/auto/web-misc/wwwin/wiki/data/pages/_views/multicast) [function.fopen]: failed to open stream: No such file or directory in /auto/web-misc/wwwin/wiki/inc/counter.php on line 10

I tried all the above solutions and no change.

It keep

I replace the code and it continues giving me the same problem.

Getting the filename of a page

Did it ever occur to you that you could simply take a look at how DokuWiki resolves the $ID to a filename internally?

/**
 * returns the full path to the meta file specified by ID and extension
 *
 * The filename is URL encoded to protect Unicode chars
 *
 * @author Steven Danz <steven-danz@kc.rr.com>
 */
function metaFN($id,$ext){
  global $conf;
  $id = cleanID($id);
  $id = str_replace(':','/',$id);
  $fn = $conf['metadir'].'/'.utf8_encodeFN($id).$ext;
  return $fn;
}

So you basically have to copy this function and replace $conf['metadir'] by realpath($conf['datadir']).'/_views'. — Markus Birth 2009-02-03 00:34.38

 
wiki/projects/php/dokuwiki/counter.txt · Last modified: 2009/02/03 00:29 by 85.179.156.67
 
Except where otherwise noted, content on this wiki is licensed under the following license:CC Attribution-Noncommercial-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki