xref: /plugin/ditaa/syntax.php (revision 05cbae881d27bfa0a9b0e51091292504e3b0e34e)
1<?php
2/**
3 * Ditaa-Plugin: Converts Ascii-Flowcharts into a png-File
4 *
5 * @license     GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author      Dennis Ploeger <develop [at] dieploegers [dot] de>
7 * @author      Christoph Mertins <c [dot] mertins [at] gmail [dot] com>
8 * @author      Andreas Gohr <andi@splitbrain.org>
9 */
10
11if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
13require_once(DOKU_PLUGIN.'syntax.php');
14
15class syntax_plugin_ditaa extends DokuWiki_Syntax_Plugin {
16
17    /**
18     * What about paragraphs?
19     */
20    function getPType(){
21        return 'normal';
22    }
23
24    /**
25     * What kind of syntax are we?
26     */
27    function getType(){
28        return 'substition';
29    }
30
31    /**
32     * Where to sort in?
33     */
34    function getSort(){
35        return 200;
36    }
37
38    /**
39     * Connect pattern to lexer
40     */
41
42    function connectTo($mode) {
43        $this->Lexer->addSpecialPattern('<ditaa.*?>\n.*?\n</ditaa>',$mode,'plugin_ditaa');
44    }
45
46    /**
47     * Handle the match
48     */
49    function handle($match, $state, $pos, &$handler) {
50        $info = $this->getInfo();
51
52        // prepare default data
53        $return = array(
54                        'width'     => 0,
55                        'height'    => 0,
56                        'antialias' => true,
57                        'edgesep'   => true,
58                        'round'     => false,
59                        'shadow'    => true,
60                        'scale'     => 1,
61                        'align'     => '',
62                        'version'   => $info['date'], //forece rebuild of images on update
63                       );
64
65
66        // prepare input
67        $lines = explode("\n",$match);
68        $conf = array_shift($lines);
69        array_pop($lines);
70
71        // match config options
72        if(preg_match('/\b(left|center|right)\b/i',$conf,$match)) $return['align'] = $match[1];
73        if(preg_match('/\b(\d+)x(\d+)\b/',$conf,$match)){
74            $return['width']  = $match[1];
75            $return['height'] = $match[2];
76        }
77        if(preg_match('/\b(\d+(\.\d+)?)X\b/',$conf,$match)) $return['scale']  = $match[1];
78        if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1];
79        if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1];
80        // match boolean toggles
81        if(preg_match_all('/\b(no)?(antialias|edgesep|round|shadow)\b/i',$conf,$matches,PREG_SET_ORDER)){
82            foreach($matches as $match){
83                $return[$match[2]] = ! $match[1];
84            }
85        }
86
87        $input = join("\n",$lines);
88        $return['md5'] = md5($input); // we only pass a hash around
89
90        // store input for later use
91        io_saveFile($this->_cachename($return,'txt'),$input);
92
93        return $return;
94    }
95
96    /**
97     * Create output
98     */
99    function render($format, &$R, $data) {
100        if($format != 'xhtml') return;
101        $img = DOKU_BASE.'lib/plugins/ditaa/ditaa.php?'.buildURLparams($data,'&');
102
103        $R->doc .= '<img src="'.$img.'" class="media'.$data['align'].'" alt=""';
104        if($data['width'])  $R->doc .= ' width="'.$data['width'].'"';
105        if($data['height']) $R->doc .= ' height="'.$data['height'].'"';
106        if($data['align'] == 'right') $ret .= ' align="right"';
107        if($data['align'] == 'left')  $ret .= ' align="left"';
108        $R->doc .= '/>';
109    }
110
111    /**
112     * Cache file is based on data
113     */
114    function _cachename($data,$ext){
115        unset($data['width']);
116        unset($data['height']);
117        unset($data['align']);
118        return getcachename(join('x',array_values($data)),'.ditaa.'.$ext);
119    }
120
121    /**
122     * Render the output remotely at ditaa.org
123     */
124    function _remote($data,$in,$out){
125        $http = new DokuHTTPClient();
126        $http->timeout=30;
127
128        $pass = array();
129        $pass['scale']   = $data['scale'];
130        $pass['timeout'] = 25;
131        $pass['grid']    = io_readFile($in);
132        if(!$data['antialias']) $pass['A'] = 'on';
133        if(!$data['shadow'])    $pass['S'] = 'on';
134        if($data['round'])      $pass['r'] = 'on';
135        if(!$data['edgesep'])   $pass['E'] = 'on';
136
137        $img = $http->post('http://ditaa.org/ditaa/render',$pass);
138        if(!$img) return false;
139
140        io_saveFile($out,$img);
141        return true;
142    }
143
144
145    /**
146     * Run the ditaa Java program
147     */
148    function _run($data,$in,$out) {
149        global $conf;
150
151        if(!file_exists($in)){
152            if($conf['debug']){
153                dbglog($in,'no such ditaa input file');
154            }
155            return false;
156        }
157
158        $cmd  = $this->getConf('java');
159        $cmd .= ' -Djava.awt.headless=true -Dfile.encoding=UTF-8 -jar';
160        $cmd .= ' '.escapeshellarg(dirname(__FILE__).'/ditaa/ditaa0_9.jar'); //ditaa jar
161        $cmd .= ' --encoding UTF-8';
162        $cmd .= ' '.escapeshellarg($in); //input
163        $cmd .= ' '.escapeshellarg($out); //output
164        $cmd .= ' -s '.escapeshellarg($data['scale']);
165        if(!$data['antialias']) $cmd .= ' -A';
166        if(!$data['shadow'])    $cmd .= ' -S';
167        if($data['round'])      $cmd .= ' -r';
168        if(!$data['edgesep'])   $cmd .= ' -E';
169
170        exec($cmd, $output, $error);
171
172        if ($error != 0){
173            if($conf['debug']){
174                dbglog(join("\n",$output),'ditaa command failed: '.$cmd);
175            }
176            return false;
177        }
178
179        return true;
180    }
181
182}
183
184