1<?php 2/** 3 * Plugin calc : petite calculatrice. 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Etienne Mauvais <emauvaisfr@yahoo.fr> 7 */ 8 9// based on http://wiki.splitbrain.org/plugin:tutorial 10 11// must be run within Dokuwiki 12if (!defined('DOKU_INC')) die(); 13 14if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 15require_once(DOKU_PLUGIN . 'syntax.php'); 16 17/** 18 * All DokuWiki plugins to extend the parser/rendering mechanism 19 * need to inherit from this class 20 */ 21class syntax_plugin_calc extends DokuWiki_Syntax_Plugin { 22 function getInfo() { 23 return array( 24 'author' => 'Etienne Mauvais', 25 'email' => 'emauvaisfr@yahoo.fr', 26 'date' => @file_get_contents(DOKU_PLUGIN.'calc/VERSION'), 27 'name' => 'Calc Plugin', 28 'desc' => $this->getLang('calc_description'), 29 'url' => 'http://www.dokuwiki.org/plugin:calc' 30 ); 31 } 32 33 function connectTo($mode) { 34 $this->Lexer->addSpecialPattern('calc:.*?=', $mode, 'plugin_calc'); 35 } 36 37 //function getType() { return 'substition'; } 38 function getType() { return 'disabled'; } 39 40 function getSort() { return 667; } 41 42 function handle($match, $state, $pos, &$handler) { 43 return array($match, $state, $pos); 44 } 45 46 function render($mode, &$renderer, $data) { 47 if ($mode == 'xhtml') { 48 //On recupere l'expression 49 $calc=split("calc:",$data[0]); 50 if (isset($calc) && isset($calc[1])) $calc=$calc[1]; 51 52 //On enleve le "=" final 53 if ($calc[strlen($calc)-1]=='=') $calc[strlen($calc)-1]=" "; 54 $calc=rtrim($calc); 55 56 //Si on a un ">" final on l'enleve et on affichera l'expression avant le resultat 57 if ($calc[strlen($calc)-1]=='>') { 58 $calc[strlen($calc)-1]=" "; 59 $affiche=true; 60 } 61 $calc=rtrim($calc); 62 63 //On retire les fonctions interdites 64 $encore=1; 65 while($encore) { 66 $encore=0; 67 $calc=preg_replace_callback("/([a-z].+?\(.*?\))/", 68 create_function('$f', 69 'GLOBAL $encore; 70 $autorisees=Array("abs", "acos", "acosh", "asin", "asinh", "atan", "atan2", "atanh", 71 "base_convert", "bindec", 72 "ceil", "cos", "cosh", 73 "decbin", "dechex", "decoct", "deg2rad", 74 "exp", "expm1", 75 "floor", "fmod", 76 "getrandmax", 77 "hexdec", "hypot", 78 "is_finite", "is_infinite", "is_nan", 79 "lcg_value", "log", "log10", "log1p", 80 "max", "min", "mt_getrandmax", "mt_rand", "mt_srand", 81 "octdec", 82 "pi", "pow", 83 "rad2deg", "rand", "round", 84 "sin", "sinh", "sqrt", "srand", 85 "tan", "tanh"); 86 87 //print " Trouve : ".$f[1]; 88 89 $nomF=explode("(",$f[1]); 90 $nomF=$nomF[0]; 91 92 if(in_array($nomF, $autorisees)) { 93 //print " -> autorisee\n"; 94 return $f[1]; 95 } 96 else { 97 //print " -> interdite !!!\n"; 98 $encore=1; 99 return ""; 100 }' 101 ), 102 $calc); 103 } 104 //On retire les ";" et les "$" 105 $calc=str_replace(";","",$calc); 106 $calc=str_replace("\$","",$calc); 107 108 //On affiche un commentaire dans le source de la page 109 $renderer->doc .= "\n<!-- Calc : $calc -->\n"; 110 $calc_propre=$calc; 111 $calc="\$n=$calc;"; 112 113 //On passe en mode track_errors (apres avoir recupere l'ancien mode) 114 $track=ini_get('track_errors'); 115 ini_set('track_errors', 'true'); 116 $php_errormsg=""; 117 try { 118 eval($calc); 119 } 120 catch (Exception $e) { 121 $renderer->doc .= "\"<b>".$this->getLang('calc_erreur')."</b> ".$e->getMessage()."\""; 122 return true; 123 } 124 //On repasse dans l'ancien mode track_error 125 ini_set('track_error', $track); 126 127 //S'il y a eu une erreur (non catchee par try) 128 if ($php_errormsg) { 129 $renderer->doc .= "\"<b>".$this->getLang('calc_erreur')."</b> ".$php_errormsg."\""; 130 return true; 131 } 132 133 //Si la valeur retournee n'est pas un nombre (ex : sqrt(-1) 134 if (is_nan($n)) { 135 $renderer->doc .= "\"".$this->getLang('calc_valeurincorrecte')."\""; 136 return true; 137 } 138 139 //Mise en forme du resultat 140 //Si on a obtenu un nombre (et pas une chaine, suite a base_convert, par exemple) 141 if ($n*1===$n) { 142 $tmp=explode('.',$n); 143 $out=number_format($tmp[0], 0, $this->getLang('calc_sepdec'), $this->getLang('calc_sepmil')); 144 if (isset($tmp[1])) $out.= $this->getLang('calc_sepdec').$tmp[1]; 145 } 146 else $out=$n; 147 148 $out=preg_replace("/ /"," ", $out); 149 150 //Si on est en mode affichage, on affiche d'abord l'expression avant le resultat 151 if ($affiche) $renderer->doc .= $calc_propre." = "; 152 $renderer->doc .= $out; 153 154 return true; 155 } 156 return false; 157 } 158} 159?> 160