1<?php
2/**
3 * Math Plugin: incorporate mathematical formulae using MathPublisher into Dokuwiki
4 *
5 * Syntax:     <m size>...mathematical formula..</m>
6 *   size      (optional) base glyph size in pixels,
7 *             if not present will use the value of $mathplugin_size global, the value
8 *             of which can be set below (default: 12)
9 *
10 * Formulae syntax:  refer http://www.xm1math.net/phpmathpublisher/doc/help.html
11 *
12 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
13 * @author     Christopher Smith <chris@jalakai.co.uk>
14 * @date       2005-12-17
15 *
16 * phpmathpublisher
17 * @link       http://www.xm1math.net/phpmathpublisher/
18 * @author     Pascal Brachet
19 */
20
21if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
22if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
23require_once(DOKU_PLUGIN.'syntax.php');
24require_once(DOKU_INC.'inc/io.php');
25
26global $conf;
27
28// -----------------------[ math plugin globals ]---------------------------------------
29global $mathplugin_size, $mathplugin_urlimg;
30
31  // default base size (pixels) of glyphs in the formulae
32  $mathplugin_size = 12;
33
34  // base url to access images, should correspond to $dirimg below.
35  // if left at default, it will be modified to add a subfolder to avoid filling
36  // the root media folder with clutter, refer _cacheExists()
37  $mathplugin_urlimg = DOKU_URL.'lib/exe/fetch.php?w=&amp;h=&amp;cache=cache&amp;media=';
38
39// -----------------------[ mathpublisher settings ]------------------------------------
40global $dirfonts,$dirimg;
41
42  // absolute path to the fonts directory (must not have '/' at end)
43  $dirfonts=dirname(__FILE__)."/phpmathpublisher/fonts";
44
45  // absolute path to the img directory (must not have '/' at end)
46  // if left at default, it will be modified to add a subfolder to avoid filling
47  // the root media folder with clutter, refer _cacheExists()
48  $dirimg=$conf['mediadir'];
49
50// ------------------------------------------------------------------------------------
51
52/**
53 * All DokuWiki plugins to extend the parser/rendering mechanism
54 * need to inherit from this class
55 */
56class syntax_plugin_math extends DokuWiki_Syntax_Plugin {
57
58    // FIXME localise
59    var $str_nopng = "PHP's gd library is missing or unable to create PNG images";
60    var $str_noft = "PHP installation missing access to freetype library";
61    var $enable = false;
62    var $msg_disable = "math plugin disabled: ";
63    var $msg_sent = false;
64
65    function syntax_plugin_math() {
66        $this->enable = $this->_requirements_ok();
67    }
68
69    /**
70     * return some info
71     */
72    function getInfo(){
73
74      return array(
75        'author' => 'Christopher Smith',
76        'email'  => 'chris@jalakai.co.uk',
77        'date'   => '2008-08-13',
78        'name'   => 'Math Plugin'.(!$this->enable ? ' (disabled)' : ''),
79        'desc'   => 'Add mathematical formulae to dokuwiki
80                     Syntax: <m size>math formulae</m>
81                     For formulae syntax visit http://www.xm1math.net/phpmathpublisher/doc/help.html'.
82                     (!$this->enable ? "\n(".$this->msg_disable.")" : ''),
83        'url'    => 'http://www.dokuwiki.org/plugin:math2',
84      );
85    }
86
87    function getType(){ return 'protected'; }
88    function getPType(){ return 'normal'; }
89    function getSort(){ return 208; }
90
91    /**
92     * Connect pattern to lexer
93     */
94    function connectTo($mode) {
95      $this->Lexer->addEntryPattern('<m(?=[^\r\n]*?>.*?</m>)',$mode,'plugin_math');
96    }
97
98    function postConnect() {
99      $this->Lexer->addExitPattern('</m>','plugin_math');
100    }
101
102    /**
103     * Handle the match
104     */
105    function handle($match, $state, $pos, &$handler){
106      global $mathplugin_size;
107
108      if ( $state == DOKU_LEXER_UNMATCHED ) {
109        list($size, $math) = preg_split('/>/u', $match, 2);   // will split into size & math formulae
110        if (!is_numeric($size)) $size = $mathplugin_size;
111
112        if (strlen($math) > 1) {
113          $c_first = $math{0};
114          $c_last = $math{strlen($math)-1};
115
116          $align = ($c_first == ' ') ? ($c_last == ' ' ? 'center' : 'right') : ($c_last == ' ' ? 'left' : 'normal');
117        } else {
118          $align = 'normal';
119        }
120
121        return (array($size, trim($math), $align));
122      }
123      return false;
124    }
125
126    /**
127     * Create output
128     */
129    function render($mode, &$renderer, $data) {
130      global $mathplugin_urlimg;
131
132      if (!$data) return;   // skip rendering for the enter and exit patterns
133      list($size, $math, $align) = $data;
134
135      if($mode == 'xhtml'){
136          // phpmathpublisher generates many E_NOTICE errors, ensure error_reporting doesn't include E_NOTICE.
137          $error_level = error_reporting();
138          error_reporting($error_level & ~E_NOTICE);
139
140          // check we have ability to create png images
141          if ($this->enable) {
142            // check we have somewhere to create our images & make them
143            if ($this->_cacheExists()) {
144                require_once(dirname(__FILE__).'/phpmathpublisher/mathpublisher.php');
145                $math_html = mathimage($math, $size, $mathplugin_urlimg);
146
147                if ($align != 'normal') {
148                    $math_html = preg_replace('/<img /i','\0 class="media'.$align.'" ',$math_html);
149                }
150
151                $renderer->doc .= $math_html;
152            } else {
153                $this->_msg("math plugin img folder is not writable", -1);
154            }
155          } else {
156            $this->_msg($this->msg_disable, -1);
157          }
158
159          // return to previous error reporting level
160          error_reporting($error_level);
161          return true;
162      }
163      return false;
164    }
165
166    function _cacheExists() {
167        global $dirimg, $mathplugin_urlimg, $conf;
168
169        // check for default setting
170        if (!isset($dirimg) || !$dirimg) { $dirimg = $conf['mediadir']; }
171        if ($dirimg == $conf['mediadir']) {
172            // we don't want to clutter the root media dir, so create our own subfolder
173            $dirimg .= "/cache_mathplugin";
174            $mathplugin_urlimg .= "cache_mathplugin%3a";
175
176            if (!@is_dir($dirimg)) {
177                $this->_mkdir($dirimg);
178            }
179        }
180
181        return @is_writable($dirimg);
182    }
183
184    // return true if php installation has required libraries/functions for mathpublisher
185    function _requirements_ok() {
186        if (!function_exists('imagepng')) {
187          $this->msg_disable .= $this->str_nopng;
188          return false;
189        }
190
191        if (!function_exists('imagettftext')) {
192          $this->msg_disable .= $this->str_noft;
193          return false;
194        }
195
196        return true;
197    }
198
199    // used to avoid multiple messages
200    function _msg($str, $lvl=0) {
201        if ($this->msg_sent) return;
202
203        msg($str, $lvl);
204        $this->msg_sent = true;
205    }
206
207    // would like to see this function in io.php :)
208    function _mkdir($d) {
209        global $conf;
210
211        umask($conf['dmask']);
212        $ok = io_mkdir_p($d);
213        umask($conf['umask']);
214        return $ok;
215    }
216
217}
218
219//Setup VIM: ex: et ts=4 enc=utf-8 :
220