*/
// based on http://wiki.splitbrain.org/plugin:tutorial
// must be run within Dokuwiki
if (!defined('DOKU_INC')) die();
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_calc extends DokuWiki_Syntax_Plugin {
function getInfo() {
return array(
'author' => 'Etienne Mauvais',
'email' => 'emauvaisfr@yahoo.fr',
'date' => @file_get_contents(DOKU_PLUGIN.'calc/VERSION'),
'name' => 'Calc Plugin',
'desc' => $this->getLang('calc_description'),
'url' => 'http://www.dokuwiki.org/plugin:calc'
);
}
function connectTo($mode) {
$this->Lexer->addSpecialPattern('calc:.*?=', $mode, 'plugin_calc');
}
//function getType() { return 'substition'; }
function getType() { return 'disabled'; }
function getSort() { return 667; }
function handle($match, $state, $pos, &$handler) {
return array($match, $state, $pos);
}
function render($mode, &$renderer, $data) {
if ($mode == 'xhtml') {
//On recupere l'expression
$calc=split("calc:",$data[0]);
if (isset($calc) && isset($calc[1])) $calc=$calc[1];
//On enleve le "=" final
if ($calc[strlen($calc)-1]=='=') $calc[strlen($calc)-1]=" ";
$calc=rtrim($calc);
//Si on a un ">" final on l'enleve et on affichera l'expression avant le resultat
if ($calc[strlen($calc)-1]=='>') {
$calc[strlen($calc)-1]=" ";
$affiche=true;
}
$calc=rtrim($calc);
//On retire les fonctions interdites
$encore=1;
while($encore) {
$encore=0;
$calc=preg_replace_callback("/([a-z].+?\(.*?\))/",
create_function('$f',
'GLOBAL $encore;
$autorisees=Array("abs", "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh",
"base_convert", "bindec",
"ceil", "cos", "cosh",
"decbin", "dechex", "decoct", "deg2rad",
"exp", "expm1",
"floor", "fmod",
"getrandmax",
"hexdec", "hypot",
"is_finite", "is_infinite", "is_nan",
"lcg_value", "log", "log10", "log1p",
"max", "min", "mt_getrandmax", "mt_rand", "mt_srand",
"octdec",
"pi", "pow",
"rad2deg", "rand", "round",
"sin", "sinh", "sqrt", "srand",
"tan", "tanh");
//print " Trouve : ".$f[1];
$nomF=explode("(",$f[1]);
$nomF=$nomF[0];
if(in_array($nomF, $autorisees)) {
//print " -> autorisee\n";
return $f[1];
}
else {
//print " -> interdite !!!\n";
$encore=1;
return "";
}'
),
$calc);
}
//On retire les ";" et les "$"
$calc=str_replace(";","",$calc);
$calc=str_replace("\$","",$calc);
//On affiche un commentaire dans le source de la page
$renderer->doc .= "\n\n";
$calc_propre=$calc;
$calc="\$n=$calc;";
//On passe en mode track_errors (apres avoir recupere l'ancien mode)
$track=ini_get('track_errors');
ini_set('track_errors', 'true');
$php_errormsg="";
try {
eval($calc);
}
catch (Exception $e) {
$renderer->doc .= "\"".$this->getLang('calc_erreur')." ".$e->getMessage()."\"";
return true;
}
//On repasse dans l'ancien mode track_error
ini_set('track_error', $track);
//S'il y a eu une erreur (non catchee par try)
if ($php_errormsg) {
$renderer->doc .= "\"".$this->getLang('calc_erreur')." ".$php_errormsg."\"";
return true;
}
//Si la valeur retournee n'est pas un nombre (ex : sqrt(-1)
if (is_nan($n)) {
$renderer->doc .= "\"".$this->getLang('calc_valeurincorrecte')."\"";
return true;
}
//Mise en forme du resultat
//Si on a obtenu un nombre (et pas une chaine, suite a base_convert, par exemple)
if ($n*1===$n) {
$tmp=explode('.',$n);
$out=number_format($tmp[0], 0, $this->getLang('calc_sepdec'), $this->getLang('calc_sepmil'));
if (isset($tmp[1])) $out.= $this->getLang('calc_sepdec').$tmp[1];
}
else $out=$n;
$out=preg_replace("/ /"," ", $out);
//Si on est en mode affichage, on affiche d'abord l'expression avant le resultat
if ($affiche) $renderer->doc .= $calc_propre." = ";
$renderer->doc .= $out;
return true;
}
return false;
}
}
?>