]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/SystemInfo.php
Clean up language/locale setting code.
[SourceForge/phpwiki.git] / lib / plugin / SystemInfo.php
1 <?php rcs_id('$Id: SystemInfo.php,v 1.3 2002-09-18 18:34:13 dairiki Exp $');
2 /**
3  * Usage: <?plugin SystemInfo all ?>
4  *        or <?plugin SystemInfo pagestats cachestats discspace hitstats ?> 
5  *        or <?plugin SystemInfo version ?> 
6  *        or <?plugin SystemInfo current_theme ?> 
7  *        or <?plugin SystemInfo PHPWIKI_DIR ?> 
8  *
9  * Provide access to phpwiki's lower level system information.
10  *   version, CHARSET, pagestats, SERVER_NAME, database, discspace, 
11  *   cachestats, userstats, linkstats, accessstats, hitstats, revisionstats,
12  *   interwikilinks, imageextensions, wikiwordregexp, availableplugins, downloadurl, ...
13  *
14  * In spirit to http://www.ecyrd.com/JSPWiki/SystemInfo.jsp
15  *
16  * Todo: Some calculations are heavy (~5-8 secs), so we should cache the result. 
17  *       In the page or with WikiPluginCached?
18  */
19 //require_once "lib/WikiPluginCached.php";
20
21 class WikiPlugin_SystemInfo
22 //extends WikiPluginCached
23 extends WikiPlugin
24 {
25     function getPluginType() {
26         return PLUGIN_CACHED_HTML;
27     }
28     function getName() {
29         return _("SystemInfo");
30     }
31
32     function getDescription() {
33         return _("Provide access to PhpWiki's lower level system information.");
34     }
35     function getExpire($dbi, $argarray, $request) {
36         return '+1800'; // 30 minutes
37     }
38     function getHtml($dbi, $argarray, $request) {
39         $loader = new WikiPluginLoader;
40         return $loader->expandPI('<?plugin SystemInfo '
41                                  . WikiPluginCached::glueArgs($argarray) // all 
42                                  . ' ?>',$request);         
43     }
44     /*
45     function getDefaultArguments() {
46         return array(
47                      'seperator' => ' ', // on multiple args
48                      );
49     }
50     */
51
52     function database() {
53         global $DBParams, $request;
54         $s  = _("db type") . ": {$DBParams['dbtype']}, ";
55         switch ($DBParams['dbtype']) {
56         case 'SQL':     // pear
57         case 'ADODB':
58             $dsn = $DBParams['dsn'];
59             $s .= _("db backend") . ": ";
60             $s .= ($DBParams['dbtype'] == 'SQL') ? 'PearDB' : 'ADODB';
61             if (preg_match('/^(\w+):/', $dsn, $m)) {
62                 $backend = $m[1];
63                 $s .= " $backend, ";
64             }
65             break;
66         case 'dba':
67             $s .= _("dba handler") . ": {$DBParams['dba_handler']}, ";
68             break;
69         case 'cvs':
70             // $s .= "cvs stuff: , ";
71             break;
72         case 'flatfile':
73             // $s .= "flatfile stuff: , ";
74             break;
75         }
76         $s .= _("timeout") . ": {$DBParams['timeout']}";
77         return $s;
78     }
79     function cachestats() {
80         global $DBParams, $request;
81         if (! defined('USECACHE') or !USECACHE)
82             return _("no cache used");
83         $dbi = $request->getDbh();
84         $cache = $dbi->_cache;
85         $s  = _("cached pagedata") . ": " . count($cache->_pagedata_cache);
86         $s .= ", " . _("cached versiondata") . ": " . count($cache->_versiondata_cache);
87         //$s .= ", glv size: " . count($cache->_glv_cache);
88         //$s .= ", cache hits: ?";
89         //$s .= ", cache misses: ?";
90         return $s;
91     }
92     function ExpireParams() {
93         global $ExpireParams;
94         $s  = sprintf(_("Keep up to %d major edits, but keep them no longer than %d days."), 
95                       $ExpireParams['major']['keep'], $ExpireParams['major']['max_age']);
96         $s .= sprintf(_(" Keep up to %d minor edits, but keep them no longer than %d days."), 
97                       $ExpireParams['minor']['keep'], $ExpireParams['minor']['max_age']);
98         $s .= sprintf(_(" Keep the latest contributions of the last %d authors up to %d days."), 
99                       $ExpireParams['author']['keep'], $ExpireParams['author']['max_age']);
100         $s .= sprintf(_(" Additionally, try to keep the latest contributions of all authors in the last %d days (even if there are more than %d of them,) but in no case keep more than %d unique author revisions."), 
101                       $ExpireParams['author']['min_age'], $ExpireParams['author']['keep'], $ExpireParams['author']['max_keep']);
102         return $s;
103     }
104     function pagestats() {
105         global $request;
106         $e = 0; $a = 0;
107         $dbi = $request->getDbh();
108         $include_empty = true;
109         $iter = $dbi->getAllPages($include_empty);
110         while ($page = $iter->next()) $e++;
111         $s  = sprintf(_("%d pages"), $e);
112         $include_empty = false;
113         $iter = $dbi->getAllPages($include_empty);
114         while ($page = $iter->next()) $a++;
115         $s  .= ", " . sprintf(_("%d not-empty pages"), $a);
116         // more bla....
117         // $s  .= ", " . sprintf(_("earliest page from %s"), $earliestdate);
118         // $s  .= ", " . sprintf(_("latest page from %s"), $latestdate);
119         // $s  .= ", " . sprintf(_("latest pagerevision from %s"), $latestrevdate);
120         return $s;
121     }
122     //What kind of link statistics?
123     //  total links in, total links out, mean links per page, ...
124     //  Any useful numbers similar to a VisualWiki interestmap? 
125     function linkstats() {
126         $s  = _("not yet");
127         return $s;
128     }
129     // number of homepages: easy
130     // number of anonymous users?
131     //   calc this from accesslog info?
132     // number of anonymous edits?
133     //   easy. related to the view/edit rate in accessstats. 
134     function userstats() {
135         global $request;
136         $dbi = $request->getDbh();
137         $h = 0;
138         $page_iter = $dbi->getAllPages(true);
139         while ($page = $page_iter->next()) {
140             if ($page->isUserPage(true)) // check if the admin is there. if not add him to the authusers.
141                 $h++;
142         }
143         $s  = sprintf(_("%d homepages"), $h);
144         // $s  .= ", " . sprintf(_("%d anonymous users"), $au); // ??
145         // $s  .= ", " . sprintf(_("%d anonymous edits"), $ae); // see recentchanges
146         // $s  .= ", " . sprintf(_("%d authenticated users"), $auth); // users with password set
147         // $s  .= ", " . sprintf(_("%d externally authenticated users"), $extauth); // query AuthDB?
148         return $s;
149     }
150     //only from logging info possible. = hitstats per time.
151     // total hits per day/month/year
152     // view/edit rate 
153     function accessstats() {
154         $s  = _("not yet");
155         return $s;
156     }
157     // only absolute numbers, not for any time interval. see accessstats
158     //  some useful number derived from the curve of the hit stats.
159     //  total, max, mean, median, stddev;
160     //  %d pages less than 3 hits (<10%)    <10% percent of the leastpopular
161     //  %d pages more than 100 hits (>90%)  >90% percent of the mostpopular
162     function hitstats() {
163         global $request;
164         $dbi = $request->getDbh();
165         $total = 0; $max = 0;
166         $hits = array();
167         $page_iter = $dbi->getAllPages(true);
168         while ($page = $page_iter->next()) {
169             if ($current = $page->getCurrentRevision() and (! $current->hasDefaultContents())) {
170                 $h = $page->get('hits');
171                 $hits[] = $h;
172                 $total += $h;
173                 $max = max($h,$max);
174             }
175         }
176         sort($hits);
177         reset($hits);
178         $n = count($hits);
179         $median_i = (int) $n / 2;
180         if (! ($n / 2))
181             $median = $hits[$median_i];
182         else
183             $median = $hits[$median_i];
184         $stddev = stddev(&$hits,$total);
185         
186         $s  = sprintf(_("total hits: %d"), $total);
187         $s .= ", " . sprintf(_("max: %d"), $max);
188         $s .= ", " . sprintf(_("mean: %2.3f"), $total / $n);
189         $s .= ", " . sprintf(_("median: %d"), $median);
190         $s .= ", " . sprintf(_("stddev: %2.3f"), $stddev);
191         $percentage = 10;
192         $mintreshold = $max * $percentage / 100.0;   // lower than 10% of the hits
193         reset($hits); $nmin = $hits[0] < $mintreshold ? 1 : 0;
194         while (next($hits) < $mintreshold)
195             $nmin++;
196         $maxtreshold = $max - $mintreshold; // more than 90% of the hits
197         end($hits); $nmax = 1;
198         while (prev($hits) > $maxtreshold)
199             $nmax++;
200         $s .= "; " . sprintf(_("%d pages with less than %d hits (<%d%%)."), $nmin, $mintreshold, $percentage);
201         $s .= " " . sprintf(_("%d page(s) with more than %d hits (>%d%%)."), $nmax, $maxtreshold, 100-$percentage);
202         return $s;
203     }
204     function revisionstats() {
205         global $request;
206         $dbi = $request->getDbh();
207         $total = 0; $max = 0;
208         $hits = array();
209         $page_iter = $dbi->getAllPages(true);
210         while ($page = $page_iter->next()) {
211             if ($current = $page->getCurrentRevision() and (! $current->hasDefaultContents())) {
212                 //$ma = $page->get('major');
213                 //$mi = $page->get('minor');
214                 ;
215             }
216         }
217         return 'not yet';
218     }
219     // size of databases/files/cvs are possible plus the known size of the app.
220     // Todo: cache this costly operation!
221     function discspace() {
222         global $DBParams;
223         $dir = PHPWIKI_DIR;
224         $appsize = `du -s $dir | cut -f1`;
225
226         if (in_array($DBParams['dbtype'],array('SQL','ADODB'))) {
227             $pagesize = 0;
228         } elseif ($DBParams['dbtype'] == 'dba') {
229             $pagesize = 0;
230             $dbdir = $DBParams['directory'];
231             if ($DBParams['dba_handler'] == 'db3')
232                 $pagesize = filesize($DBParams['directory']."/wiki_pagedb.db3") / 1024;
233             // if issubdirof($dbdir, $dir) $appsize -= $pagesize;
234         } else { // flatfile, cvs
235             $dbdir = $DBParams['directory'];
236             $pagesize = `du -s $dbdir`;
237             // if issubdirof($dbdir, $dir) $appsize -= $pagesize;
238         }
239         $s  = sprintf(_("Application size: %d Kb"), $appsize);
240         if ($pagesize)
241             $s  .= ", " . sprintf(_("Pagedata size: %d Kb", $pagesize));
242         return $s;
243     }
244
245     function inlineimages () {
246         return implode(' ',explode('|',$GLOBALS['InlineImages']));
247     }
248     function wikinameregexp () {
249         return $GLOBALS['WikiNameRegexp'];
250     }
251     function allowedprotocols () {
252         return implode(' ',explode('|',$GLOBALS['AllowedProtocols']));
253     }
254     function available_plugins () {
255         $fileset = new FileSet(FindFile('lib/plugin'),'*.php');
256         $list = $fileset->getFiles();
257         natcasesort($list);
258         reset($list);
259         return sprintf(_("Total %d plugins: "),count($list)) . 
260             implode(', ',array_map(create_function('$f','return substr($f,0,-4);'),$list));
261     }
262     function supported_languages () {
263         $available_languages = array('en');
264         $dir_root = PHPWIKI_DIR . '/locale/'; 
265         $dir = dir($dir_root);
266         if ($dir) {
267             while($entry = $dir->read()) {
268                 if (is_dir($dir_root.$entry) and (substr($entry,0,1) != '.') and 
269                     $entry != 'po' and $entry != 'CVS') {
270                     array_push($available_languages,$entry);
271                 }
272             }
273             $dir->close();
274         }
275         natcasesort($available_languages);
276
277         return sprintf(_("Total %d languages: "),count($available_languages)) . 
278             implode(', ',$available_languages) . ". " .
279             sprintf(_("Current language: '%s'"), $GLOBALS['LANG']) .
280             ((DEFAULT_LANGUAGE != $GLOBALS['LANG']) 
281               ? ". " . sprintf(_("System default: '%s'"), DEFAULT_LANGUAGE)
282               : '');
283     }
284
285     function supported_themes () {
286         global $Theme;
287         $available_themes = array(); 
288         $dir_root = PHPWIKI_DIR . '/themes/'; 
289         $dir = dir($dir_root);
290         if ($dir) {
291             while($entry = $dir->read()) {
292                 if (is_dir($dir_root.$entry) and (substr($entry,0,1) != '.') 
293                     and $entry!='CVS') {
294                     array_push($available_themes,$entry);
295                 }
296             }
297             $dir->close();
298         }
299         natcasesort($available_themes);
300         return sprintf(_("Total %d themes: "),count($available_themes)) . 
301             implode(', ',$available_themes) . ". " .
302             sprintf(_("Current theme: '%s'"), $Theme->_name) . 
303             ((THEME != $Theme->_name)
304               ? ". " . sprintf(_("System default: '%s'"), THEME)
305               : '');
306     }
307
308
309     function call ($arg, &$availableargs) {
310         if (!empty($availableargs[$arg]))
311             return $availableargs[$arg]();
312         elseif (method_exists($this,$arg)) // any defined SystemInfo->method()system
313             return call_user_func_array(array(&$this, $arg),'');
314         elseif (defined($arg) and $arg != 'ADMIN_PASSWD') // any defined constant
315             return constant($arg);
316         else
317             return $this->error(sprintf(_("unknown argument '%s' to SystemInfo"),$arg));
318     }
319
320
321     function run($dbi, $argstr, $request) {
322         // don't parse argstr for name=value pairs. instead we use just 'name'
323         //$args = $this->getArgs($argstr, $request);
324         $args['seperator'] = ' ';
325         $availableargs = // name => callback + 0 args
326             array ('appname' => create_function('',"return 'PhpWiki';"),
327                    'version' => create_function('',"return sprintf('%s',PHPWIKI_VERSION);"),
328                    'LANG'    => create_function('','return $GLOBALS["LANG"];'),
329                    'LC_ALL'  => create_function('','return setlocale(LC_ALL, 0);'),
330                    'current_language' => create_function('','return $GLOBALS["LANG"];'),
331                    'system_language' => create_function('','return DEFAULT_LANGUAGE;'),
332                    'current_theme' => create_function('','return $GLOBALS["Theme"]->_name;'),
333                    'system_theme'  => create_function('','return THEME;'),
334                    // more here or as method.
335                    '' => create_function('',"return 'dummy';")
336                    );
337         // split the argument string by any number of commas or space characters,
338         // which include " ", \r, \t, \n and \f
339         $allargs = preg_split("/[\s,]+/",$argstr,-1,PREG_SPLIT_NO_EMPTY);
340         if (in_array('all',$allargs) or in_array('table',$allargs)) {
341             $allargs = array('appname'          => _("Application name"),
342                              'version'          => _("PhpWiki engine version"),
343                              'database'         => _("Database"),
344                              'cachestats'       => _("Cache statistics"),
345                              'pagestats'        => _("Page statistics"),
346                              //'revisionstats'          => _("Page revision statistics"),
347                              //'linkstats'      => _("Link statistics"),
348                              'userstats'        => _("User statistics"),
349                              //'accessstats'    => _("Access statistics"),
350                              'hitstats'         => _("Hit statistics"),
351 //                             'discspace'      => _("Harddisc usage"),
352                              'expireparams'     => _("Expiry parameters"),
353                              'wikinameregexp'   => _("Wikiname regexp"),
354                              'allowedprotocols' => _("Allowed protocols"),
355                              'inlineimages'     => _("Inline images"),
356                              'available_plugins'   => _("Available plugins"),
357                              'supported_languages' => _("Supported languages"),
358                              'supported_themes'    => _("Supported themes"),
359 //                           '' => _(""),
360                              '' => _("")
361                              );
362             $table = HTML::table(array('border' => 1,'cellspacing' => 3,'cellpadding' => 3));
363             foreach ($allargs as $arg => $desc) {
364                 if (!$arg) continue;
365                 if (!$desc) $desc = _($arg);
366                 $table->pushContent(HTML::tr(HTML::td(HTML::strong($desc . ':')),
367                                              HTML::td(HTML($this->call($arg,&$availableargs)))));
368             }
369             return $table;
370         } else {
371             $output = '';
372             foreach ($allargs as $arg) {
373                 $o = $this->call($arg,&$availableargs);
374                 if (is_object($o)) return $o;
375                 else $output .= ($o . $args['seperator']);
376             }
377             // if more than one arg, remove the trailing seperator
378             if ($output) $output = substr($output,0,- strlen($args['seperator']));
379             return HTML($output);
380         }
381     }
382 }
383
384 /* // autolisp stdlib
385 ;;; Median of the sorted list of numbers. 50% is above and 50% below
386 ;;; "center of a distribution"
387 ;;; Ex: (std-median (std-make-list 100 std-%random)) => 0.5 +- epsilon
388 ;;;     (std-median (std-make-list 100 (lambda () (std-random 10))))
389 ;;;       => 4.0-5.0 [0..9]
390 ;;;     (std-median (std-make-list 99  (lambda () (std-random 10))))
391 ;;;       => 4-5
392 ;;;     (std-median '(0 0 2 4 12))      => 2
393 ;;;     (std-median '(0 0 4 12))        => 2.0
394 (defun STD-MEDIAN (numlst / l)
395   (setq numlst (std-sort numlst '<))            ; don't remove duplicates
396   (if (= 0 (rem (setq l (length numlst)) 2))    ; if even length
397     (* 0.5 (+ (nth (/ l 2) numlst)              ; force float!
398               (nth (1- (/ l 2)) numlst)))       ; fixed by Serge Pashkov
399     (nth (/ l 2) numlst)))
400
401 */
402 function median($hits) {
403     sort($hits);
404     reset($hits);
405     $n = count($hits);
406     $median = (int) $n / 2;
407     if (! ($n % 2)) // proper rounding on even length
408         return ($hits[$median] + $hits[$median-1]) * 0.5;
409     else
410         return $hits[$median];
411 }
412
413 function rsum($a, $b) {
414     $a += $b;
415     return $a;
416 }
417 function mean(&$hits,$total=false) {
418     $n = count($hits);
419     if (!$total) $total = array_reduce($hits,'rsum');
420     return (float) $total / ($n * 1.0);
421 }
422 function gensym($prefix = "_gensym") {
423     $i = 0;
424     while (isset($GLOBALS[$prefix.$i])) $i++;
425     return $prefix.$i;
426 }
427
428 /* // autolisp stdlib
429 (defun STD-STANDARD-DEVIATION (numlst / n _dev_m r)
430   (setq n      (length numlst)
431         _dev_m (std-mean numlst)
432         r      (mapcar (function (lambda (x) (std-sqr (- x _dev_m)))) numlst))
433   (sqrt (* (std-mean r) (/ n (float (- n 1))))))
434 */
435 /*
436 function stddev(&$hits,$total=false) {
437     $n = count($hits);
438     if (!$total) $total = array_reduce($hits,'rsum');
439     $mean = gensym("_mean");
440     $GLOBALS[$mean] = $total / $n;
441     $cb = "global ${$mean}; return (\$i-${$mean})*(\$i-${$mean});";
442     $r = array_map(create_function('$i',"global ${$mean}; return (\$i-${$mean})*(\$i-${$mean});"),$hits);
443     unset($GLOBALS[$mean]);
444     return (float) sqrt(mean($r,$total) * ($n / (float)($n -1)));
445 }
446 */
447 function stddev(&$hits,$total=false) {
448     $n = count($hits);
449     if (!$total) $total = array_reduce($hits,'rsum');
450     $GLOBALS['mean'] = $total / $n;
451     $r = array_map(create_function('$i','global $mean; return ($i-$mean)*($i-$mean);'),$hits);
452     unset($GLOBALS['mean']);
453     return (float) sqrt(mean($r,$total) * ($n / (float)($n -1)));
454 }
455
456 // Local Variables:
457 // mode: php
458 // tab-width: 8
459 // c-basic-offset: 4
460 // c-hanging-comment-ender-p: nil
461 // indent-tabs-mode: nil
462 // End:
463 ?>