Table of Contents

Stats - plugin

stats plugin by Paco Avila
Displays some wiki stats.

Last updated on 2005-08-01. Provides Syntax.
No compatibility info given!

Similar to statdisplay.

Tagged with maybe.broken, statistics.

Syntax

Show Hall Of Fame

This option shows a table with the top ten contributors to the wiki:

~~STATS:hof~~

Show number of users

Shows the number of registered users in the wiki:

~~STATS:users~~

Show number of pages

Show the number of pages in the wiki:

~~STATS:pages~~

Show number of entries

Show the number of entries in the wiki. Each entry is a <h2> header.

~~STATS:entries~~

Examples

See this plugin in action at http://www.guia-ubuntu.org/breezy/doku.php?id=estadisticas. That site now seems to be using Mediawiki? [Edit by Anon: Please FIXME then.]

Plugin

<?php
/**
 * Info Plugin: Displays information about various DokuWiki internals
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Andreas Gohr <andi@splitbrain.org>
 */
 
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');
 
/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_stats extends DokuWiki_Syntax_Plugin {
 
    /**
     * return some info
     */
    function getInfo(){
        return array(
            'author' => 'Paco Avila (Monkiki)',
            'email'  => 'monkiki@gmail.com',
            'date'   => '2005-08-01',
            'name'   => 'Stats Plugin',
            'desc'   => 'Displays some statistics about DokuWiki',
            'url'    => 'http://www.guia-ubuntu.org/breezy',
        );
    }
 
    /**
     * What kind of syntax are we?
     */
    function getType(){
        return 'substition';
    }
 
    /**
     * Where to sort in?
     */ 
    function getSort(){
        return 129;
    }
 
    /**
     * Connect pattern to lexer
     */
    function connectTo($mode) {
        $this->Lexer->addSpecialPattern('~~STATS:\w+~~',$mode,'plugin_stats');
    }
 
    /**
     * Handle the match
     */
    function handle($match, $state, $pos, &$handler){
        $match = substr($match,8,-2);
        return array(strtolower($match));
    }
 
    /**
     * Create output
     */
    function render($mode, &$renderer, $data) {
      if($mode == 'xhtml'){
        //handle various info stuff
        switch ($data[0]){
          case 'hof':
            $renderer->doc .= $this->_hof_xhtml();
            break;
          case 'users':
            $renderer->doc .= $this->_users_xhtml();
            break;
          case 'pages':
            $renderer->doc .= $this->_pages_xhtml();
            break;
          case 'entries':
            $renderer->doc .= $this->_entries_xhtml();
            break;
          default:
            $renderer->doc .= "unknown stat: ".htmlspecialchars($data[0]);
        }
        return true;
      }
      return false;
    }
 
    /**
     * list all installed syntax plugins
     *
     * uses some of the original renderer methods
     */
 
    /**
     * lists all known syntax modes and their sorting value
     */
    function _hof_xhtml() {
      $user_info =  $this->_get_names();
 
      //$ret = "<div style=\"position:absolute; left:685px; top:288px;\">";
      $ret = "<div class=\"info_hof\">";
      $ret .= "<table class=\"inline\">";
      $ret .= "<tr><th class=\"centeralign\" colspan=\"3\">Hall Of Fame</th></tr>";
      $handle = fopen(DOKU_INC."data/changes.log", "r");
 
      while ($log = fscanf($handle, "%s\t%s\t%s\t%s\t%s\n")) {
        list ($time, $ip, $page, $user, $action) = $log;
        if ($user != "" && $user != "created" && $user != "creado" &&
            $page != "wiki:playground") {
          $user_value[$user]++;
        }
      }
 
      fclose($handle);
      arsort($user_value);
 
      foreach ($user_value as $key => $value) {
        if ($i++ % 2) {
          $color = "#feefd6";
        } else {
          $color = "#f2f0ed";
        }
        if ($i < 11) {
           $ret .= "<tr bgcolor=\"".$color."\"><td class=\"leftalign\"><b>".$i."</b></td><td class=\"leftalign\">".$user_info[$key]."</td><td>".$value."</td></tr>";
	}
      }
 
      $ret .= "</table>";
      $ret .= "</div>";
 
      return $ret;
    }
 
    function _get_names() {
      if ($handle = fopen(DOKU_INC."conf/users.auth.php", "r")) {
        while ($line = fgets($handle)) {
          if (substr($line, 0, 1) != "#" && strlen(trim($line)) > 0) {
            $data = explode(":", $line);
            $ret[$data[0]] = $data[2];
          }
        }
 
        fclose($handle);
      }
 
      return $ret;
    }
 
    function _users_xhtml() {
      if ($handle = fopen(DOKU_INC."conf/users.auth.php", "r")) {
        while ($line = fgets($handle)) {
          if (substr($line, 0, 1) != "#" && strlen(trim($line)) > 0) {
            $cont++;
          }
        }
 
        fclose($handle);
      }
 
      return $cont;
    }
 
    function _pages_xhtml() {
      return $this->_pages_xhtml_r(DOKU_INC."data/pages");
    }
 
    function _pages_xhtml_r($path) {
      if ($pdir = opendir($path)) {
        while ($file = readdir($pdir)) {
          if ($file != "." && $file != "..") {
            if (is_file($path."/".$file)) {
              $tmp++;
            } else if (is_dir($path."/".$file) && $file != "wiki") {
              $tmp += $this->_pages_xhtml_r($path."/".$file);
            }
          }
        }
        closedir($pdir);
      }
 
      return $tmp;
    }
 
    function _entries_xhtml() {
      return $this->_entries_xhtml_r(DOKU_INC."data/pages");
    }
 
    function _entries_xhtml_r($path) {
      if ($pdir = opendir($path)) {
        while ($file = readdir($pdir)) {
          if ($file != "." && $file != "..") {
            if (is_file($path."/".$file)) {
              $tmp += $this->_entries_xhtml_get($path."/".$file);
            } else if (is_dir($path."/".$file) && $file != "wiki") {
              $tmp += $this->_entries_xhtml_r($path."/".$file);
            }
          }
        }
        closedir($pdir);
      }
 
      return $tmp;
    }
 
    function _entries_xhtml_get($file) {
      if ($pf = fopen($file, "r")) {
        while ($line = fgets($pf, 4096)) {
          if (preg_match("/^(\s)*(==+)(.+?)(==+)(\s*)$/", $line, $regs)) {
            if ($regs[2] == "=====") {
              $count++;
            }
          }
        }
        fclose($pf);
      }
 
     return $count;
    }
}
 
//Setup VIM: ex: et ts=4 enc=utf-8 :

Discussion

How to make it work with ACL build on a mySQL database, rather than the simple users.auth.conf file ?

I don't know. Perphaps it should connect to the MySQL database. My wiki don't use this configuration, sorry.

Hi, there is probably some problem with this script. I just created a new DokuWiki with no entry and only one user. The following error shows up using all statistics:

Warning: arsort() expects parameter 1 to be array, null given in /var/www/dokuwiki-2005-09-22/lib/plugins/stats/syntax.php on line 116

Yes, the code is not perfect. It is a little bug that I will fix soon. When I developed this plugin, my wiki had several entries and users :)

Where do I install this code? Is there a plugin manager version I can just point to? thanks!

Actually I don't know how do this. I'll try to.

Do you plan to add stats by namespaces (namely pages stats)? Mathias 2006-06-25


Could the Hall of fame table be made smaller if less than ten users exist? – Wonko 2006-07-01

Could you please mention the steps of installing this plugin and using it?

Could you please explain what to name the directory and the file name?


I've applyed the following change in my installation :

--- syntax.php.org   2006-08-14 18:36:46.000000000 -0300
+++ syntax.php 2006-08-14 14:38:55.000000000 -0300
@@ -96,12 +96,14 @@
      * lists all known syntax modes and their sorting value
      */
     function _hof_xhtml() {
+      global $lang;
+
       $user_info =  $this->_get_names();
 
       //$ret = "<div style=\"position:absolute; left:685px; top:288px;\">";
       $ret = "<div class=\"info_hof\">";
       $ret .= "<table class=\"inline\">";
-      $ret .= "<tr><th class=\"centeralign\" colspan=\"3\">Hall Of Fame</th></tr>";
+      $ret .= "<tr><th class=\"centeralign\" colspan=\"3\">".$this->getLang('hall_fame')."</th></tr>";
       $handle = fopen(DOKU_INC."data/changes.log", "r");
 
       while ($log = fscanf($handle, "%s\t%s\t%s\t%s\t%s\n")) {

Next I created the lang directory with three files :

lang/en/lang.php

<?php
/**
 * english language file
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Fernando Roxo <roxo@roxo.org>
 */
 
$lang['hall_fame']  = 'Hall of Fame';


lang/pt-br/lang.php

<?php
/**
 * Brazilian Portuguese language file
 *
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Fernando Roxo <roxo@roxo.org>
 */
 
$lang['hall_fame']  = 'Hall da Fama';
//Setup VIM: ex: et ts=2 enc=utf-8 :


The third one was for european portuguese (pt) and has the same content of the pt-br file.
With this my “Hall o Fame” became “Hall da Fama”, as usual in portugese.

HTH –FernandoRoxo

:!: The Plugin don't work anymore with the new release of DokuWiki, the new Changeslogs are now in …/data/meta/*.changes, not in …/data/changes.log.

The following patch makes the plugin work with the new global changelog. (Tested with release 2006-11-06) — Per Foreby 2006-11-27 12:40
--- syntax.php.ORIG     2006-11-19 23:31:32.000000000 +0100
+++ syntax.php  2006-11-27 12:15:35.294059504 +0100
@@ -96,23 +96,23 @@
      * lists all known syntax modes and their sorting value
      */
     function _hof_xhtml() {
+      global $conf;
+
       $user_info =  $this->_get_names();
       
       //$ret = "<div style=\"position:absolute; left:685px; top:288px;\">";
       $ret = "<div class=\"info_hof\">";
       $ret .= "<table class=\"inline\">";
       $ret .= "<tr><th class=\"centeralign\" colspan=\"3\">Hall Of Fame</th></tr>";
-      $handle = fopen(DOKU_INC."data/changes.log", "r");
       
-      while ($log = fscanf($handle, "%s\t%s\t%s\t%s\t%s\n")) {
-        list ($time, $ip, $page, $user, $action) = $log;
-        if ($user != "" && $user != "created" && $user != "creado" &&
-            $page != "wiki:playground") {
-          $user_value[$user]++;
+      $lines = file($conf['changelog']);
+      foreach ($lines as $line) {
+        $parsed = parseChangelogLine($line);
+        if (!ereg("^playground:", $parsed['id'])
+            && strpbrk($parsed['type'], 'CEe')) {
+          $user_value[$parsed['user']]++;
         }
       }
-      
-      fclose($handle);
       arsort($user_value);
  
       foreach ($user_value as $key => $value) {

! maybe interesting, strpbrk() not exists in PHP 4, only PHP 5.

Replace it with $parsed['type'] == 'C' || $parsed['type'] == 'E' || $parsed['type'] == 'e' if you have to run PHP4.

Down't work in me wiki, it reads only _dokuwiki.changes and not all the *.changes(?!)

_dokuwiki.changes is a composite changelog, so there is no need to parse the individual log files.
But if i use the “stats”, i see only 4 edits instead of 500, only the 4 witch are in _dokuwiki.changes. “stats” is in a doc in the root directory and in a namespace, same result(?!)
I guess the 4 edits are made after the upgrade to 2006-11-06? It seems like the upgrade splits the old changelog into the new separate files, but all new changes are also written to _dokuwiki.changes. It should be trivial to do a manual sync:
cd data/meta
cat `find . -name '*.changes'|grep -v _dokuwiki.changes` > _dokuwiki.changes
Don't sync your old changelog with the new changelog!
See changelog for details on the new format. The recent changes cache (kept in /data/meta/_dokuwiki.changes) is trimmed daily!
The Hall Of Fame part of this plugin needs a number of changes. I've debugged mine so HOF works! (even with LDAP authentication - which didn't before). I'll post a patch when I've finished it! - JC


For all those ppl who are asking how to install this plugin I have packed the files into tgz's. Just unpack the tgz in the lib/plugins directory. I changed the original source-code with the patches mention here in the discussion that were working in my case. The first change is the one related to the language-file implementation. The second is the update for the changes mentioned by Per Foreby on the 2006-11-27 12:40 related to the changelog. In my situation the

~~STATS:hof~~

isn't parsed with contents. This needs updating in future in my situation. I packed versions specific for php4 and php5 since the function strpbrk is php5-only. For the php4-version I used the code from the answer in this discussion.
php4
php5


Thanks for the hard work, but when I put the “hof” command, there is a error: “arsort() expects parameter 1 to be array, null given in E:\…\lib\plugins\stats\syntax.php on line 117”. I use php4, 2007-6 Dokuwiki release, and the others commands works as expected. Any suggestion?


Hi ! This plugin doesn't work for me ? after investigating, data/changes.log doesn't exist and if I touch it, it doesn't fill up ? So I used data/meta/_dokuwiki.changes.

Furthermore, I use AD (LDAP) login, so names aren't filled the way you try touse them. I also did a little hack.

See the diff :

--- stats/syntax.php	2008-08-12 13:28:29.000000000 +0200
+++ ../syntax.php	2008-08-14 16:25:27.000000000 +0200
@@ -102,10 +102,10 @@
       $ret = "<div class=\"info_hof\">";
       $ret .= "<table class=\"inline\">";
       $ret .= "<tr><th class=\"centeralign\" colspan=\"3\">Hall Of Fame</th></tr>";
-      $handle = fopen(DOKU_INC."data/changes.log", "r");
+      $handle = fopen(DOKU_INC."data/meta/_dokuwiki.changes", "r");
 
       while ($log = fscanf($handle, "%s\t%s\t%s\t%s\t%s\n")) {
-        list ($time, $ip, $page, $user, $action) = $log;
+        list ($time, $ip, $action, $page, $user, $detail) = $log;
         if ($user != "" && $user != "created" && $user != "creado" &&
             $page != "wiki:playground") {
           $user_value[$user]++;
@@ -122,6 +122,8 @@
           $color = "#f2f0ed";
         }
         if ($i < 11) {
+           if (! isset($user_info[$key]))
+              $user_info[$key] = $key;
            $ret .= "<tr bgcolor=\"".$color."\"><td class=\"leftalign\"><b>".$i."</b></td><td class=\"leftalign\">".$user_info[$key]."</td><td>".$value."</td></tr>";
 	}
       }

Nicolas