xref: /plugin/graphviz/syntax.php (revision 517bd8367891ed3eeda89c7608688f50ccdd0d7a)
1<?php
2/**
3 * graphviz-Plugin: Parses graphviz-blocks
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Carl-Christian Salvesen <calle@ioslo.net>
7 * @author     Andreas Gohr <andi@splitbrain.org>
8 */
9
10if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11require_once(DOKU_INC.'inc/init.php');
12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
13require_once(DOKU_PLUGIN.'syntax.php');
14
15class syntax_plugin_graphviz 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 100;
36    }
37
38    /**
39     * Connect pattern to lexer
40     */
41    function connectTo($mode) {
42        $this->Lexer->addSpecialPattern('<graphviz.*?>\n.*?\n</graphviz>',$mode,'plugin_graphviz');
43    }
44
45    /**
46     * Handle the match
47     */
48    function handle($match, $state, $pos, &$handler) {
49        $info = $this->getInfo();
50
51        // prepare default data FIXME
52        $return = array(
53                        'data'      => '',
54                        'width'     => 0,
55                        'height'    => 0,
56                        'layout'    => 'dot',
57#                        'antialias' => true,
58#                        'edgesep'   => true,
59#                        'round'     => false,
60#                        'shadow'    => true,
61#                        'scale'     => 1,
62                        'align'     => '',
63                        'version'   => $info['date'], //force rebuild of images on update
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(dot|neato|twopi|circo|fdp)\b/i',$conf,$match)){
78            $return['layout'] = strtolower($match[1]);
79        }
80        if(preg_match('/\b(\d+(\.\d+)?)X\b/',$conf,$match)) $return['scale']  = $match[1];
81        if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1];
82        if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1];
83        // match boolean toggles
84        if(preg_match_all('/\b(no)?(antialias|edgesep|round|shadow)\b/i',$conf,$matches,PREG_SET_ORDER)){
85            foreach($matches as $match){
86                $return[$match[2]] = ! $match[1];
87            }
88        }
89
90        $return['data'] = join("\n",$lines);
91
92        return $return;
93    }
94
95    /**
96     * Create output
97     */
98    function render($format, &$R, $data) {
99        if($format != 'xhtml') return;
100
101        if($this->getConf('path')){
102            // run graphviz on our own server
103            $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data,'&');
104        }else{
105
106#FIXME
107            // use ditaa.org for rendering
108            $pass = array(
109                'grid'  => $data['data'],
110                'scale' => $data['scale']
111            );
112            if(!$data['antialias']) $pass['A'] = 'on';
113            if(!$data['shadow'])    $pass['S'] = 'on';
114            if($data['round'])      $pass['r'] = 'on';
115            if(!$data['edgesep'])   $pass['E'] = 'on';
116            $pass['timeout'] = 25;
117
118            $img = 'http://ditaa.org/ditaa/render?'.buildURLparams($pass,'&');
119            $img = ml($img,array('w'=>$data['width'],'h'=>$data['height']));
120        }
121
122        $R->doc .= '<img src="'.$img.'" class="media'.$data['align'].'" alt=""';
123        if($data['width'])  $R->doc .= ' width="'.$data['width'].'"';
124        if($data['height']) $R->doc .= ' height="'.$data['height'].'"';
125        if($data['align'] == 'right') $ret .= ' align="right"';
126        if($data['align'] == 'left')  $ret .= ' align="left"';
127        $R->doc .= '/>';
128    }
129
130
131    /**
132     * Run the graphviz program
133     */
134    function _run($data,$cache) {
135        global $conf;
136
137        $temp = tempnam($conf['tmpdir'],'graphviz_');
138        io_saveFile($temp,$data['data']);
139
140        $cmd  = $this->getConf('path');
141        $cmd .= ' -Tpng';
142        $cmd .= ' -K'.$data['layout'];
143        $cmd .= ' -o'.escapeshellarg($cache); //output
144        $cmd .= ' '.escapeshellarg($temp); //input
145
146        exec($cmd, $output, $error);
147        @unlink($temp);
148
149        if ($error != 0){
150            if($conf['debug']){
151                dbglog(join("\n",$output),'graphviz command failed: '.$cmd);
152            }
153            return false;
154        }
155        return true;
156    }
157
158}
159
160
161
162