[dokuwiki] Re: Autosubmit popularity data (FS2025)

  • From: Guillaume Turri <guillaume.turri@xxxxxxxxx>
  • To: dokuwiki@xxxxxxxxxxxxx
  • Date: Sun, 5 Dec 2010 16:49:59 +0100

Hi,

thank you for your precisions, and sorry for this late answer (I've been a
bit busy this week)

2010/11/27 Michael Hamann <michael@xxxxxxxxxxxxxxxx>

> - use Doku_Form instead of manually generating the HTML for the form
>
I've looked a bit at it, but it seems to be a bit overkill since we only
need two fields and a submit button...

- for the code in the admin part that is used in the action part a
>  helper part or just another php file would imho be good/better style.
>
I never made helper plugins, so I didn't realized it would be relevant here.
Here is a new patch which add such a plugin. Does it seems to make sense
this way?


> - Probably loading the admin/helper part only in the handler would make
>  sense as that handler won't be called every time the plugin is loaded
>
 It seems to me that it would be needed every time.
Indeed, it seems to me that the function which gather the data should be in
the helper plugin, since the action plugin needs it. And this data is needed
in the html() function.
Am I wrong? Should the gather() function remains in the admin plugin.


- I think when the submission of the data fails a message file should be
>  written [...]
>

> - When the manual submission fails a possibility could be
>  offered to submit the data directly from the browser like it is done
>  now.
>
Those are indeed interesting suggestions. I'll try to implement them this
week.

Regards,
Guillaume
diff --git a/lib/plugins/popularity/action.php 
b/lib/plugins/popularity/action.php
new file mode 100644
index 0000000..82ad38e
--- /dev/null
+++ b/lib/plugins/popularity/action.php
@@ -0,0 +1,43 @@
+<?php
+
+require_once(DOKU_PLUGIN.'action.php');
+require_once(DOKU_PLUGIN.'popularity/admin.php');
+
+class action_plugin_popularity extends Dokuwiki_Action_Plugin {
+    var $helper;
+
+    function action_plugin_popularity(){
+        $this->helper = $this->loadHelper('popularity', false);
+    }
+
+    /**
+     * Register its handlers with the dokuwiki's event controller
+     */
+    function register(&$controller) {
+        $controller->register_hook('INDEXER_TASKS_RUN', 'AFTER',  $this, 
'_autosubmit', array());
+    }
+
+    function _autosubmit(&$event, $param){
+        if ( !$this->helper->isAutosubmitEnabled() || 
$this->_isTooEarlyToSubmit() ){
+            return;
+        }
+
+        //Update the last time we sent data before we actually send it,
+        //to avoid sending it several time in a fraction of second
+        touch ( $this->helper->autosubmitFile );
+
+        $this->helper->sendData( $this->helper->gatherAsString() );
+
+        $event->stopPropagation();
+        $event->preventDefault();
+    }
+
+    /**
+     * Check if it's time to send autosubmit data
+     * (we should have check the autosubmit is enabled first)
+     */
+    function _isTooEarlyToSubmit(){
+        $lastSubmit = @filemtime($this->helper->autosubmitFile);
+        return $lastSubmit + 24*60*60*30 > time();
+    }
+}
diff --git a/lib/plugins/popularity/admin.php b/lib/plugins/popularity/admin.php
index 71ea407..1224766 100644
--- a/lib/plugins/popularity/admin.php
+++ b/lib/plugins/popularity/admin.php
@@ -13,21 +13,14 @@ if(!defined('DOKU_INC')) die();
  * need to inherit from this class
  */
 class admin_plugin_popularity extends DokuWiki_Admin_Plugin {
-    var $version = '2010-09-17';
+    var $version;
+    var $helper;
 
+    function admin_plugin_popularity(){
+        $this->helper = $this->loadHelper('popularity', false);
 
-    /**
-     * return some info
-     */
-    function getInfo(){
-        return array(
-            'author' => 'Andreas Gohr',
-            'email'  => 'andi@xxxxxxxxxxxxxx',
-            'date'   => $this->version,
-            'name'   => 'Popularity Feedback Plugin',
-            'desc'   => 'Send anonymous data about your wiki to the 
developers.',
-            'url'    => 'http://www.dokuwiki.org/plugin:popularity',
-        );
+        $pluginInfo = $this->getInfo();
+        $this->version = $pluginInfo['date'];
     }
 
     /**
@@ -56,204 +49,50 @@ class admin_plugin_popularity extends 
DokuWiki_Admin_Plugin {
      * handle user request
      */
     function handle() {
-    }
-
-    /**
-     * Output HTML form
-     */
-    function html() {
-        echo $this->locale_xhtml('intro');
-
-        flush();
-        $data = $this->_gather();
-        echo '<form method="post" 
action="http://update.dokuwiki.org/popularity.php"; accept-charset="utf-8">';
-        echo '<fieldset style="width: 60%;">';
-        echo '<textarea class="edit" rows="10" cols="80" readonly="readonly" 
name="data">';
-        foreach($data as $key => $val){
-            if(is_array($val)) foreach($val as $v){
-                echo hsc($key)."\t".hsc($v)."\n";
-            }else{
-                echo hsc($key)."\t".hsc($val)."\n";
-            }
-        }
-        echo '</textarea><br />';
-        echo '<input type="submit" class="button" 
value="'.$this->getLang('submit').'"/>';
-        echo '</fieldset>';
-        echo '</form>';
-
-//        dbg($data);
-    }
-
-
-    /**
-     * Gather all information
-     */
-    function _gather(){
-        global $conf;
-        global $auth;
-        $data = array();
-        $phptime = ini_get('max_execution_time');
-        @set_time_limit(0);
-
-        // version
-        $data['anon_id'] = md5(auth_cookiesalt());
-        $data['version'] = getVersion();
-        $data['popversion'] = $this->version;
-        $data['language'] = $conf['lang'];
-        $data['now']      = time();
-
-        // some config values
-        $data['conf_useacl']   = $conf['useacl'];
-        $data['conf_authtype'] = $conf['authtype'];
-        $data['conf_template'] = $conf['template'];
-
-        // number and size of pages
-        $list = array();
-        search($list,$conf['datadir'],array($this,'_search_count'),'','');
-        $data['page_count']    = $list['file_count'];
-        $data['page_size']     = $list['file_size'];
-        $data['page_biggest']  = $list['file_max'];
-        $data['page_smallest'] = $list['file_min'];
-        $data['page_nscount']  = $list['dir_count'];
-        $data['page_nsnest']   = $list['dir_nest'];
-        if($list['file_count']) $data['page_avg'] = $list['file_size'] / 
$list['file_count'];
-        $data['page_oldest']   = $list['file_oldest'];
-        unset($list);
-
-        // number and size of media
-        $list = array();
-        
search($list,$conf['mediadir'],array($this,'_search_count'),array('all'=>true));
-        $data['media_count']    = $list['file_count'];
-        $data['media_size']     = $list['file_size'];
-        $data['media_biggest']  = $list['file_max'];
-        $data['media_smallest'] = $list['file_min'];
-        $data['media_nscount']  = $list['dir_count'];
-        $data['media_nsnest']   = $list['dir_nest'];
-        if($list['file_count']) $data['media_avg'] = $list['file_size'] / 
$list['file_count'];
-        unset($list);
-
-        // number and size of cache
-        $list = array();
-        
search($list,$conf['cachedir'],array($this,'_search_count'),array('all'=>true));
-        $data['cache_count']    = $list['file_count'];
-        $data['cache_size']     = $list['file_size'];
-        $data['cache_biggest']  = $list['file_max'];
-        $data['cache_smallest'] = $list['file_min'];
-        if($list['file_count']) $data['cache_avg'] = $list['file_size'] / 
$list['file_count'];
-        unset($list);
-
-        // number and size of index
-        $list = array();
-        
search($list,$conf['indexdir'],array($this,'_search_count'),array('all'=>true));
-        $data['index_count']    = $list['file_count'];
-        $data['index_size']     = $list['file_size'];
-        $data['index_biggest']  = $list['file_max'];
-        $data['index_smallest'] = $list['file_min'];
-        if($list['file_count']) $data['index_avg'] = $list['file_size'] / 
$list['file_count'];
-        unset($list);
-
-        // number and size of meta
-        $list = array();
-        
search($list,$conf['metadir'],array($this,'_search_count'),array('all'=>true));
-        $data['meta_count']    = $list['file_count'];
-        $data['meta_size']     = $list['file_size'];
-        $data['meta_biggest']  = $list['file_max'];
-        $data['meta_smallest'] = $list['file_min'];
-        if($list['file_count']) $data['meta_avg'] = $list['file_size'] / 
$list['file_count'];
-        unset($list);
-
-        // number and size of attic
-        $list = array();
-        
search($list,$conf['olddir'],array($this,'_search_count'),array('all'=>true));
-        $data['attic_count']    = $list['file_count'];
-        $data['attic_size']     = $list['file_size'];
-        $data['attic_biggest']  = $list['file_max'];
-        $data['attic_smallest'] = $list['file_min'];
-        if($list['file_count']) $data['attic_avg'] = $list['file_size'] / 
$list['file_count'];
-        $data['attic_oldest']   = $list['file_oldest'];
-        unset($list);
-
-        // user count
-        if($auth && $auth->canDo('getUserCount')){
-            $data['user_count'] = $auth->getUserCount();
-        }
-
-        // calculate edits per day
-        $list = @file($conf['metadir'].'/_dokuwiki.changes');
-        $count = count($list);
-        if($count > 2){
-            $first = (int) substr(array_shift($list),0,10);
-            $last  = (int) substr(array_pop($list),0,10);
-            $dur = ($last - $first)/(60*60*24); // number of days in the 
changelog
-            $data['edits_per_day'] = $count/$dur;
+        //Send the data
+        if ( isset($_REQUEST['data']) ){
+            $this->helper->sendData( $_REQUEST['data'] );
+            //Deal with the autosubmit option
+            $this->_enableAutosubmit( isset($_REQUEST['autosubmit']) );
         }
-        unset($list);
-
-        // plugins
-        $data['plugin'] = plugin_list();
-
-        // pcre info
-        if(defined('PCRE_VERSION')) $data['pcre_version'] = PCRE_VERSION;
-        $data['pcre_backtrack'] = ini_get('pcre.backtrack_limit');
-        $data['pcre_recursion'] = ini_get('pcre.recursion_limit');
-
-        // php info
-        $data['os'] = PHP_OS;
-        $data['webserver'] = $_SERVER['SERVER_SOFTWARE'];
-        $data['php_version'] = phpversion();
-        $data['php_sapi'] = php_sapi_name();
-        $data['php_memory'] = $this->_to_byte(ini_get('memory_limit'));
-        $data['php_exectime'] = $phptime;
-        $data['php_extension'] = get_loaded_extensions();
-
-        return $data;
     }
 
-
-    function _search_count(&$data,$base,$file,$type,$lvl,$opts){
-        // traverse
-        if($type == 'd'){
-            if($data['dir_nest'] < $lvl) $data['dir_nest'] = $lvl;
-            $data['dir_count']++;
-            return true;
-        }
-
-        //only search txt files if 'all' option not set
-        if($opts['all'] || substr($file,-4) == '.txt'){
-            $size = filesize($base.'/'.$file);
-            $date = filemtime($base.'/'.$file);
-            $data['file_count']++;
-            $data['file_size'] += $size;
-            if(!isset($data['file_min']) || $data['file_min'] > $size) 
$data['file_min'] = $size;
-            if($data['file_max'] < $size) $data['file_max'] = $size;
-            if(!isset($data['file_oldest']) || $data['file_oldest'] > $date) 
$data['file_oldest'] = $date;
+    function _enableAutosubmit( $enable ){
+        if ( $enable ){
+            io_saveFile( $this->helper->autosubmitFile, ' ');
+        } else {
+            @unlink($this->helper->autosubmitFile);
         }
-
-        return false;
     }
 
     /**
-     * Convert php.ini shorthands to byte
-     *
-     * @author <gilthans dot NO dot SPAM at gmail dot com>
-     * @link   http://de3.php.net/manual/en/ini.core.php#79564
+     * Output HTML form
      */
-    function _to_byte($v){
-        $l = substr($v, -1);
-        $ret = substr($v, 0, -1);
-        switch(strtoupper($l)){
-            case 'P':
-                $ret *= 1024;
-            case 'T':
-                $ret *= 1024;
-            case 'G':
-                $ret *= 1024;
-            case 'M':
-                $ret *= 1024;
-            case 'K':
-                $ret *= 1024;
-            break;
+    function html() {
+        if ( isset($_REQUEST['data']) ){
+            echo $this->locale_xhtml('submitted');
+        } else {
+
+            echo $this->locale_xhtml('intro');
+
+            flush();
+            echo '<form method="post" action="'. script()  .'" 
accept-charset="utf-8">';
+            echo '<fieldset style="width: 60%;">';
+            echo '<textarea class="edit" rows="10" cols="80" 
readonly="readonly" name="data">';
+            echo $this->helper->gatherAsString();
+            echo '</textarea><br />';
+            echo '<label for="autosubmit">';
+            echo '<input type="checkbox" name="autosubmit" id="autosubmit" '
+                . ($this->helper->isAutosubmitEnabled() ? 'checked' : '' )
+                . '/>' . $this->getLang('autosubmit') .'<br />';
+            echo '</label>';
+            echo '<input type="submit" class="button" 
value="'.$this->getLang('submit').'"/>';
+            echo '<input type="hidden" name="do" value="admin">';
+            echo '<input type="hidden" name="page" value="popularity">';
+            echo '</fieldset>';
+            echo '</form>';
+
+            //        dbg($data);
         }
-        return $ret;
     }
 }
diff --git a/lib/plugins/popularity/helper.php 
b/lib/plugins/popularity/helper.php
new file mode 100644
index 0000000..8dc1156
--- /dev/null
+++ b/lib/plugins/popularity/helper.php
@@ -0,0 +1,245 @@
+<?php
+
+class helper_plugin_popularity extends Dokuwiki_Plugin {
+    /**
+     * The url where the data should be sent
+     */
+    var $submitUrl = 'http://update.dokuwiki.org/popularity.php';
+
+    /**
+     * Name of the file which determine if the the autosubmit is enabled,
+     * and when it was submited for the las time
+     */
+    var $autosubmitFile;
+
+    function helper_plugin_popularity(){
+        global $conf;
+        $this->autosubmitFile = $conf['cachedir'].'/autosubmit.txt';
+    }
+
+    function getMethods(){
+        $result = array();
+        $result[] = array(
+                'name'   => 'isAutoSubmitEnabled',
+                'desc'   => 'Check if autosubmit is enabled',
+                'params' => array(),
+                'return' => array('result' => 'bool')
+                );
+        $result[] = array(
+                'name'   => 'sendData',
+                'desc'   => 'Send the popularity data',
+                'params' => array('data' => 'string'),
+                'return' => array()
+                );
+        $result[] = array(
+                'name' => 'gatherAsString',
+                'desc' => 'Gather the popularity data',
+                'params' => array(),
+                'return' => array('data' => 'string')
+                );
+        return $result;
+
+    }
+
+    /**
+     * Check if autosubmit is enabled
+     * @return TRUE if we should send data once a month, FALSE otherwise
+     */
+    function isAutoSubmitEnabled(){
+        return @file_exists($this->autosubmitFile);
+    }
+
+    function sendData($data){
+        $httpClient = new DokuHTTPClient();
+        $httpClient->sendRequest($this->submitUrl, $data, 'POST');
+    }
+
+    /**
+     * Gather all information
+     * @return The popularity data as a string
+     */
+    function gatherAsString(){
+        $data = $this->_gather();
+        $string = '';
+        foreach($data as $key => $val){
+            if(is_array($val)) foreach($val as $v){
+                $string .=  hsc($key)."\t".hsc($v)."\n";
+            }else{
+                $string .= hsc($key)."\t".hsc($val)."\n";
+            }
+        }
+        return $string;
+    }
+
+    /**
+     * Gather all information
+     * @return The popularity data as an array
+     */
+    function _gather(){
+        global $conf;
+        global $auth;
+        $data = array();
+        $phptime = ini_get('max_execution_time');
+        @set_time_limit(0);
+
+        // version
+        $data['anon_id'] = md5(auth_cookiesalt());
+        $data['version'] = getVersion();
+        $data['popversion'] = $this->version;
+        $data['language'] = $conf['lang'];
+        $data['now']      = time();
+
+        // some config values
+        $data['conf_useacl']   = $conf['useacl'];
+        $data['conf_authtype'] = $conf['authtype'];
+        $data['conf_template'] = $conf['template'];
+
+        // number and size of pages
+        $list = array();
+        search($list,$conf['datadir'],array($this,'_search_count'),'','');
+        $data['page_count']    = $list['file_count'];
+        $data['page_size']     = $list['file_size'];
+        $data['page_biggest']  = $list['file_max'];
+        $data['page_smallest'] = $list['file_min'];
+        $data['page_nscount']  = $list['dir_count'];
+        $data['page_nsnest']   = $list['dir_nest'];
+        if($list['file_count']) $data['page_avg'] = $list['file_size'] / 
$list['file_count'];
+        $data['page_oldest']   = $list['file_oldest'];
+        unset($list);
+
+        // number and size of media
+        $list = array();
+        
search($list,$conf['mediadir'],array($this,'_search_count'),array('all'=>true));
+        $data['media_count']    = $list['file_count'];
+        $data['media_size']     = $list['file_size'];
+        $data['media_biggest']  = $list['file_max'];
+        $data['media_smallest'] = $list['file_min'];
+        $data['media_nscount']  = $list['dir_count'];
+        $data['media_nsnest']   = $list['dir_nest'];
+        if($list['file_count']) $data['media_avg'] = $list['file_size'] / 
$list['file_count'];
+        unset($list);
+
+        // number and size of cache
+        $list = array();
+        
search($list,$conf['cachedir'],array($this,'_search_count'),array('all'=>true));
+        $data['cache_count']    = $list['file_count'];
+        $data['cache_size']     = $list['file_size'];
+        $data['cache_biggest']  = $list['file_max'];
+        $data['cache_smallest'] = $list['file_min'];
+        if($list['file_count']) $data['cache_avg'] = $list['file_size'] / 
$list['file_count'];
+        unset($list);
+
+        // number and size of index
+        $list = array();
+        
search($list,$conf['indexdir'],array($this,'_search_count'),array('all'=>true));
+        $data['index_count']    = $list['file_count'];
+        $data['index_size']     = $list['file_size'];
+        $data['index_biggest']  = $list['file_max'];
+        $data['index_smallest'] = $list['file_min'];
+        if($list['file_count']) $data['index_avg'] = $list['file_size'] / 
$list['file_count'];
+        unset($list);
+
+        // number and size of meta
+        $list = array();
+        
search($list,$conf['metadir'],array($this,'_search_count'),array('all'=>true));
+        $data['meta_count']    = $list['file_count'];
+        $data['meta_size']     = $list['file_size'];
+        $data['meta_biggest']  = $list['file_max'];
+        $data['meta_smallest'] = $list['file_min'];
+        if($list['file_count']) $data['meta_avg'] = $list['file_size'] / 
$list['file_count'];
+        unset($list);
+
+        // number and size of attic
+        $list = array();
+        
search($list,$conf['olddir'],array($this,'_search_count'),array('all'=>true));
+        $data['attic_count']    = $list['file_count'];
+        $data['attic_size']     = $list['file_size'];
+        $data['attic_biggest']  = $list['file_max'];
+        $data['attic_smallest'] = $list['file_min'];
+        if($list['file_count']) $data['attic_avg'] = $list['file_size'] / 
$list['file_count'];
+        $data['attic_oldest']   = $list['file_oldest'];
+        unset($list);
+
+        // user count
+        if($auth && $auth->canDo('getUserCount')){
+            $data['user_count'] = $auth->getUserCount();
+        }
+
+        // calculate edits per day
+        $list = @file($conf['metadir'].'/_dokuwiki.changes');
+        $count = count($list);
+        if($count > 2){
+            $first = (int) substr(array_shift($list),0,10);
+            $last  = (int) substr(array_pop($list),0,10);
+            $dur = ($last - $first)/(60*60*24); // number of days in the 
changelog
+            $data['edits_per_day'] = $count/$dur;
+        }
+        unset($list);
+
+        // plugins
+        $data['plugin'] = plugin_list();
+
+        // pcre info
+        if(defined('PCRE_VERSION')) $data['pcre_version'] = PCRE_VERSION;
+        $data['pcre_backtrack'] = ini_get('pcre.backtrack_limit');
+        $data['pcre_recursion'] = ini_get('pcre.recursion_limit');
+
+        // php info
+        $data['os'] = PHP_OS;
+        $data['webserver'] = $_SERVER['SERVER_SOFTWARE'];
+        $data['php_version'] = phpversion();
+        $data['php_sapi'] = php_sapi_name();
+        $data['php_memory'] = $this->_to_byte(ini_get('memory_limit'));
+        $data['php_exectime'] = $phptime;
+        $data['php_extension'] = get_loaded_extensions();
+
+        return $data;
+    }
+
+    function _search_count(&$data,$base,$file,$type,$lvl,$opts){
+        // traverse
+        if($type == 'd'){
+            if($data['dir_nest'] < $lvl) $data['dir_nest'] = $lvl;
+            $data['dir_count']++;
+            return true;
+        }
+
+        //only search txt files if 'all' option not set
+        if($opts['all'] || substr($file,-4) == '.txt'){
+            $size = filesize($base.'/'.$file);
+            $date = filemtime($base.'/'.$file);
+            $data['file_count']++;
+            $data['file_size'] += $size;
+            if(!isset($data['file_min']) || $data['file_min'] > $size) 
$data['file_min'] = $size;
+            if($data['file_max'] < $size) $data['file_max'] = $size;
+            if(!isset($data['file_oldest']) || $data['file_oldest'] > $date) 
$data['file_oldest'] = $date;
+        }
+
+        return false;
+    }
+
+    /**
+     * Convert php.ini shorthands to byte
+     *
+     * @author <gilthans dot NO dot SPAM at gmail dot com>
+     * @link   http://de3.php.net/manual/en/ini.core.php#79564
+     */
+    function _to_byte($v){
+        $l = substr($v, -1);
+        $ret = substr($v, 0, -1);
+        switch(strtoupper($l)){
+            case 'P':
+                $ret *= 1024;
+            case 'T':
+                $ret *= 1024;
+            case 'G':
+                $ret *= 1024;
+            case 'M':
+                $ret *= 1024;
+            case 'K':
+                $ret *= 1024;
+            break;
+        }
+        return $ret;
+    }
+}
diff --git a/lib/plugins/popularity/lang/en/lang.php 
b/lib/plugins/popularity/lang/en/lang.php
index c9912b7..01e4435 100644
--- a/lib/plugins/popularity/lang/en/lang.php
+++ b/lib/plugins/popularity/lang/en/lang.php
@@ -2,3 +2,4 @@
 
 $lang['name'] = 'Popularity Feedback (may take some time to load)';
 $lang['submit'] = 'Send Data';
+$lang['autosubmit'] = 'Automatically send data once a month (may be 
(un)selected later)';
diff --git a/lib/plugins/popularity/lang/en/submitted.txt 
b/lib/plugins/popularity/lang/en/submitted.txt
new file mode 100644
index 0000000..30f2784
--- /dev/null
+++ b/lib/plugins/popularity/lang/en/submitted.txt
@@ -0,0 +1,3 @@
+====== Popularity Feedback ======
+
+The data has been sent succesfully.
diff --git a/lib/plugins/popularity/plugin.info.txt 
b/lib/plugins/popularity/plugin.info.txt
new file mode 100644
index 0000000..d475d20
--- /dev/null
+++ b/lib/plugins/popularity/plugin.info.txt
@@ -0,0 +1,7 @@
+base    popularity
+author  Andreas Gohr
+email   andi@xxxxxxxxxxxxxx
+date    2010-09-17
+name    Popularity Feedback Plugin
+desc    Send anonymous data about your wiki to the developers.
+url     http://www.dokuwiki.org/plugin:popularity

Other related posts: