Completed
Push — sidebaracl ( 7a112d...7c3e4a )
by Andreas
04:38
created

lib/plugins/popularity/helper.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Popularity Feedback Plugin
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 */
7
8
class helper_plugin_popularity extends Dokuwiki_Plugin {
9
    /**
10
     * The url where the data should be sent
11
     */
12
    var $submitUrl = 'http://update.dokuwiki.org/popularity.php';
13
14
    /**
15
     * Name of the file which determine if the the autosubmit is enabled,
16
     * and when it was submited for the last time
17
     */
18
    var $autosubmitFile;
19
20
    /**
21
     * File where the last error which happened when we tried to autosubmit, will be log
22
     */
23
    var $autosubmitErrorFile;
24
25
    /**
26
     * Name of the file which determine when the popularity data was manually
27
     * submitted for the last time
28
     * (If this file doesn't exist, the data has never been sent)
29
     */
30
    var $popularityLastSubmitFile;
31
32
33
    function __construct(){
34
        global $conf;
35
        $this->autosubmitFile = $conf['cachedir'].'/autosubmit.txt';
36
        $this->autosubmitErrorFile = $conf['cachedir'].'/autosubmitError.txt';
37
        $this->popularityLastSubmitFile = $conf['cachedir'].'/lastSubmitTime.txt';
38
    }
39
40
    /**
41
     * Return methods of this helper
42
     *
43
     * @return array with methods description
44
     */
45
    function getMethods(){
46
        $result = array();
47
        $result[] = array(
48
                'name'   => 'isAutoSubmitEnabled',
49
                'desc'   => 'Check if autosubmit is enabled',
50
                'params' => array(),
51
                'return' => array('result' => 'bool')
52
                );
53
        $result[] = array(
54
                'name'   => 'sendData',
55
                'desc'   => 'Send the popularity data',
56
                'params' => array('data' => 'string'),
57
                'return' => array()
58
                );
59
        $result[] = array(
60
                'name' => 'gatherAsString',
61
                'desc' => 'Gather the popularity data',
62
                'params' => array(),
63
                'return' => array('data' => 'string')
64
                );
65
        $result[] = array(
66
                'name'   => 'lastSentTime',
67
                'desc'   => 'Compute the last time popularity data was sent',
68
                'params' => array(),
69
                'return' => array('data' => 'int')
70
                );
71
        return $result;
72
73
    }
74
75
    /**
76
     * Check if autosubmit is enabled
77
     *
78
     * @return boolean TRUE if we should send data once a month, FALSE otherwise
79
     */
80
    function isAutoSubmitEnabled(){
81
        return file_exists($this->autosubmitFile);
82
    }
83
84
    /**
85
     * Send the data, to the submit url
86
     *
87
     * @param string $data The popularity data
88
     * @return string An empty string if everything worked fine, a string describing the error otherwise
89
     */
90
    function sendData($data){
91
        $error = '';
92
        $httpClient = new DokuHTTPClient();
93
        $status = $httpClient->sendRequest($this->submitUrl, array('data' => $data), 'POST');
94
        if ( ! $status ){
95
            $error = $httpClient->error;
0 ignored issues
show
The property error cannot be accessed from this context as it is declared private in class HTTPClient.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
96
        }
97
        return $error;
98
    }
99
100
    /**
101
     * Compute the last time the data was sent. If it has never been sent, we return 0.
102
     *
103
     * @return int
104
     */
105
    function lastSentTime(){
106
        $manualSubmission = @filemtime($this->popularityLastSubmitFile);
107
        $autoSubmission   = @filemtime($this->autosubmitFile);
108
109
        return max((int) $manualSubmission, (int) $autoSubmission);
110
    }
111
112
    /**
113
     * Gather all information
114
     *
115
     * @return string The popularity data as a string
116
     */
117
    function gatherAsString(){
118
        $data = $this->_gather();
119
        $string = '';
120
        foreach($data as $key => $val){
121
            if(is_array($val)) foreach($val as $v){
122
                $string .=  hsc($key)."\t".hsc($v)."\n";
123
            }else{
124
                $string .= hsc($key)."\t".hsc($val)."\n";
125
            }
126
        }
127
        return $string;
128
    }
129
130
    /**
131
     * Gather all information
132
     *
133
     * @return array The popularity data as an array
134
     */
135
    function _gather(){
136
        global $conf;
137
        /** @var $auth DokuWiki_Auth_Plugin */
138
        global $auth;
139
        $data = array();
140
        $phptime = ini_get('max_execution_time');
141
        @set_time_limit(0);
142
        $pluginInfo = $this->getInfo();
143
144
        // version
145
        $data['anon_id'] = md5(auth_cookiesalt());
146
        $data['version'] = getVersion();
147
        $data['popversion'] = $pluginInfo['date'];
148
        $data['language'] = $conf['lang'];
149
        $data['now']      = time();
150
        $data['popauto']  = (int) $this->isAutoSubmitEnabled();
151
152
        // some config values
153
        $data['conf_useacl']   = $conf['useacl'];
154
        $data['conf_authtype'] = $conf['authtype'];
155
        $data['conf_template'] = $conf['template'];
156
157
        // number and size of pages
158
        $list = array();
159
        search($list,$conf['datadir'],array($this,'_search_count'),array('all'=>false),'');
160
        $data['page_count']    = $list['file_count'];
161
        $data['page_size']     = $list['file_size'];
162
        $data['page_biggest']  = $list['file_max'];
163
        $data['page_smallest'] = $list['file_min'];
164
        $data['page_nscount']  = $list['dir_count'];
165
        $data['page_nsnest']   = $list['dir_nest'];
166
        if($list['file_count']) $data['page_avg'] = $list['file_size'] / $list['file_count'];
167
        $data['page_oldest']   = $list['file_oldest'];
168
        unset($list);
169
170
        // number and size of media
171
        $list = array();
172
        search($list,$conf['mediadir'],array($this,'_search_count'),array('all'=>true));
173
        $data['media_count']    = $list['file_count'];
174
        $data['media_size']     = $list['file_size'];
175
        $data['media_biggest']  = $list['file_max'];
176
        $data['media_smallest'] = $list['file_min'];
177
        $data['media_nscount']  = $list['dir_count'];
178
        $data['media_nsnest']   = $list['dir_nest'];
179
        if($list['file_count']) $data['media_avg'] = $list['file_size'] / $list['file_count'];
180
        unset($list);
181
182
        // number and size of cache
183
        $list = array();
184
        search($list,$conf['cachedir'],array($this,'_search_count'),array('all'=>true));
185
        $data['cache_count']    = $list['file_count'];
186
        $data['cache_size']     = $list['file_size'];
187
        $data['cache_biggest']  = $list['file_max'];
188
        $data['cache_smallest'] = $list['file_min'];
189
        if($list['file_count']) $data['cache_avg'] = $list['file_size'] / $list['file_count'];
190
        unset($list);
191
192
        // number and size of index
193
        $list = array();
194
        search($list,$conf['indexdir'],array($this,'_search_count'),array('all'=>true));
195
        $data['index_count']    = $list['file_count'];
196
        $data['index_size']     = $list['file_size'];
197
        $data['index_biggest']  = $list['file_max'];
198
        $data['index_smallest'] = $list['file_min'];
199
        if($list['file_count']) $data['index_avg'] = $list['file_size'] / $list['file_count'];
200
        unset($list);
201
202
        // number and size of meta
203
        $list = array();
204
        search($list,$conf['metadir'],array($this,'_search_count'),array('all'=>true));
205
        $data['meta_count']    = $list['file_count'];
206
        $data['meta_size']     = $list['file_size'];
207
        $data['meta_biggest']  = $list['file_max'];
208
        $data['meta_smallest'] = $list['file_min'];
209
        if($list['file_count']) $data['meta_avg'] = $list['file_size'] / $list['file_count'];
210
        unset($list);
211
212
        // number and size of attic
213
        $list = array();
214
        search($list,$conf['olddir'],array($this,'_search_count'),array('all'=>true));
215
        $data['attic_count']    = $list['file_count'];
216
        $data['attic_size']     = $list['file_size'];
217
        $data['attic_biggest']  = $list['file_max'];
218
        $data['attic_smallest'] = $list['file_min'];
219
        if($list['file_count']) $data['attic_avg'] = $list['file_size'] / $list['file_count'];
220
        $data['attic_oldest']   = $list['file_oldest'];
221
        unset($list);
222
223
        // user count
224
        if($auth && $auth->canDo('getUserCount')){
225
            $data['user_count'] = $auth->getUserCount();
226
        }
227
228
        // calculate edits per day
229
        $list = @file($conf['metadir'].'/_dokuwiki.changes');
230
        $count = count($list);
231
        if($count > 2){
232
            $first = (int) substr(array_shift($list),0,10);
233
            $last  = (int) substr(array_pop($list),0,10);
234
            $dur = ($last - $first)/(60*60*24); // number of days in the changelog
235
            $data['edits_per_day'] = $count/$dur;
236
        }
237
        unset($list);
238
239
        // plugins
240
        $data['plugin'] = plugin_list();
241
242
        // pcre info
243
        if(defined('PCRE_VERSION')) $data['pcre_version'] = PCRE_VERSION;
244
        $data['pcre_backtrack'] = ini_get('pcre.backtrack_limit');
245
        $data['pcre_recursion'] = ini_get('pcre.recursion_limit');
246
247
        // php info
248
        $data['os'] = PHP_OS;
249
        $data['webserver'] = $_SERVER['SERVER_SOFTWARE'];
250
        $data['php_version'] = phpversion();
251
        $data['php_sapi'] = php_sapi_name();
252
        $data['php_memory'] = $this->_to_byte(ini_get('memory_limit'));
253
        $data['php_exectime'] = $phptime;
254
        $data['php_extension'] = get_loaded_extensions();
255
256
        // plugin usage data
257
        $this->_add_plugin_usage_data($data);
258
259
        return $data;
260
    }
261
262
    protected function _add_plugin_usage_data(&$data){
263
        $pluginsData = array();
264
        trigger_event('PLUGIN_POPULARITY_DATA_SETUP', $pluginsData);
265
        foreach($pluginsData as $plugin => $d){
266
           if ( is_array($d) ) {
267
               foreach($d as $key => $value){
268
                   $data['plugin_' . $plugin . '_' . $key] = $value;
269
               }
270
           } else {
271
               $data['plugin_' . $plugin] = $d;
272
           }
273
        }
274
    }
275
276
    /**
277
     * Callback to search and count the content of directories in DokuWiki
278
     *
279
     * @param array &$data  Reference to the result data structure
280
     * @param string $base  Base usually $conf['datadir']
281
     * @param string $file  current file or directory relative to $base
282
     * @param string $type  Type either 'd' for directory or 'f' for file
283
     * @param int    $lvl   Current recursion depht
284
     * @param array  $opts  option array as given to search()
285
     * @return bool
286
     */
287
    function _search_count(&$data,$base,$file,$type,$lvl,$opts){
288
        // traverse
289
        if($type == 'd'){
290
            if($data['dir_nest'] < $lvl) $data['dir_nest'] = $lvl;
291
            $data['dir_count']++;
292
            return true;
293
        }
294
295
        //only search txt files if 'all' option not set
296
        if($opts['all'] || substr($file,-4) == '.txt'){
297
            $size = filesize($base.'/'.$file);
298
            $date = filemtime($base.'/'.$file);
299
            $data['file_count']++;
300
            $data['file_size'] += $size;
301
            if(!isset($data['file_min']) || $data['file_min'] > $size) $data['file_min'] = $size;
302
            if($data['file_max'] < $size) $data['file_max'] = $size;
303
            if(!isset($data['file_oldest']) || $data['file_oldest'] > $date) $data['file_oldest'] = $date;
304
        }
305
306
        return false;
307
    }
308
309
    /**
310
     * Convert php.ini shorthands to byte
311
     *
312
     * @author <gilthans dot NO dot SPAM at gmail dot com>
313
     * @link   http://de3.php.net/manual/en/ini.core.php#79564
314
     *
315
     * @param string $v
316
     * @return int|string
317
     */
318
    function _to_byte($v){
319
        $l = substr($v, -1);
320
        $ret = substr($v, 0, -1);
321
        switch(strtoupper($l)){
322
            /** @noinspection PhpMissingBreakStatementInspection */
323
            case 'P':
324
                $ret *= 1024;
325
            /** @noinspection PhpMissingBreakStatementInspection */
326
            case 'T':
327
                $ret *= 1024;
328
            /** @noinspection PhpMissingBreakStatementInspection */
329
            case 'G':
330
                $ret *= 1024;
331
            /** @noinspection PhpMissingBreakStatementInspection */
332
            case 'M':
333
                $ret *= 1024;
334
            case 'K':
335
                $ret *= 1024;
336
            break;
337
        }
338
        return $ret;
339
    }
340
}
341