xref: /plugin/graphviz/syntax.php (revision 9d954370cc99a7ad567bfa05ad196b85cc4fda55)
1903f28d7SAndreas Gohr<?php
2903f28d7SAndreas Gohr/**
3903f28d7SAndreas Gohr * graphviz-Plugin: Parses graphviz-blocks
4903f28d7SAndreas Gohr *
5903f28d7SAndreas Gohr * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6903f28d7SAndreas Gohr * @author     Carl-Christian Salvesen <calle@ioslo.net>
7517bd836SAndreas Gohr * @author     Andreas Gohr <andi@splitbrain.org>
8903f28d7SAndreas Gohr */
9903f28d7SAndreas Gohr
10903f28d7SAndreas Gohrif(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
11903f28d7SAndreas Gohrrequire_once(DOKU_INC.'inc/init.php');
12903f28d7SAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
13903f28d7SAndreas Gohrrequire_once(DOKU_PLUGIN.'syntax.php');
14903f28d7SAndreas Gohr
15903f28d7SAndreas Gohrclass syntax_plugin_graphviz extends DokuWiki_Syntax_Plugin {
16903f28d7SAndreas Gohr
17517bd836SAndreas Gohr    /**
18517bd836SAndreas Gohr     * What about paragraphs?
19517bd836SAndreas Gohr     */
20517bd836SAndreas Gohr    function getPType(){
21517bd836SAndreas Gohr        return 'normal';
22903f28d7SAndreas Gohr    }
23903f28d7SAndreas Gohr
24903f28d7SAndreas Gohr    /**
25903f28d7SAndreas Gohr     * What kind of syntax are we?
26903f28d7SAndreas Gohr     */
27903f28d7SAndreas Gohr    function getType(){
28517bd836SAndreas Gohr        return 'substition';
29903f28d7SAndreas Gohr    }
30903f28d7SAndreas Gohr
31903f28d7SAndreas Gohr    /**
32903f28d7SAndreas Gohr     * Where to sort in?
33903f28d7SAndreas Gohr     */
34903f28d7SAndreas Gohr    function getSort(){
35903f28d7SAndreas Gohr        return 100;
36903f28d7SAndreas Gohr    }
37903f28d7SAndreas Gohr
38903f28d7SAndreas Gohr    /**
39903f28d7SAndreas Gohr     * Connect pattern to lexer
40903f28d7SAndreas Gohr     */
41903f28d7SAndreas Gohr    function connectTo($mode) {
42517bd836SAndreas Gohr        $this->Lexer->addSpecialPattern('<graphviz.*?>\n.*?\n</graphviz>',$mode,'plugin_graphviz');
43903f28d7SAndreas Gohr    }
44903f28d7SAndreas Gohr
45903f28d7SAndreas Gohr    /**
46903f28d7SAndreas Gohr     * Handle the match
47903f28d7SAndreas Gohr     */
48517bd836SAndreas Gohr    function handle($match, $state, $pos, &$handler) {
49517bd836SAndreas Gohr        $info = $this->getInfo();
50903f28d7SAndreas Gohr
5167682e69SAndreas Gohr        // prepare default data
52517bd836SAndreas Gohr        $return = array(
53517bd836SAndreas Gohr                        'data'      => '',
54517bd836SAndreas Gohr                        'width'     => 0,
55517bd836SAndreas Gohr                        'height'    => 0,
56517bd836SAndreas Gohr                        'layout'    => 'dot',
57517bd836SAndreas Gohr                        'align'     => '',
58517bd836SAndreas Gohr                        'version'   => $info['date'], //force rebuild of images on update
59517bd836SAndreas Gohr                       );
60903f28d7SAndreas Gohr
61517bd836SAndreas Gohr        // prepare input
62517bd836SAndreas Gohr        $lines = explode("\n",$match);
63517bd836SAndreas Gohr        $conf = array_shift($lines);
64517bd836SAndreas Gohr        array_pop($lines);
65517bd836SAndreas Gohr
66517bd836SAndreas Gohr        // match config options
67517bd836SAndreas Gohr        if(preg_match('/\b(left|center|right)\b/i',$conf,$match)) $return['align'] = $match[1];
68517bd836SAndreas Gohr        if(preg_match('/\b(\d+)x(\d+)\b/',$conf,$match)){
69517bd836SAndreas Gohr            $return['width']  = $match[1];
70517bd836SAndreas Gohr            $return['height'] = $match[2];
71903f28d7SAndreas Gohr        }
72517bd836SAndreas Gohr        if(preg_match('/\b(dot|neato|twopi|circo|fdp)\b/i',$conf,$match)){
73517bd836SAndreas Gohr            $return['layout'] = strtolower($match[1]);
74903f28d7SAndreas Gohr        }
75517bd836SAndreas Gohr        if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1];
76517bd836SAndreas Gohr        if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1];
77517bd836SAndreas Gohr
78517bd836SAndreas Gohr        $return['data'] = join("\n",$lines);
79517bd836SAndreas Gohr
80517bd836SAndreas Gohr        return $return;
81517bd836SAndreas Gohr    }
82517bd836SAndreas Gohr
83903f28d7SAndreas Gohr    /**
84903f28d7SAndreas Gohr     * Create output
8567682e69SAndreas Gohr     *
8667682e69SAndreas Gohr     * @todo latex and ODT support
87903f28d7SAndreas Gohr     */
88517bd836SAndreas Gohr    function render($format, &$R, $data) {
89517bd836SAndreas Gohr        if($format != 'xhtml') return;
90517bd836SAndreas Gohr
9167682e69SAndreas Gohr        $img = $this->_imgurl($data);
92517bd836SAndreas Gohr        $R->doc .= '<img src="'.$img.'" class="media'.$data['align'].'" alt=""';
93517bd836SAndreas Gohr        if($data['width'])  $R->doc .= ' width="'.$data['width'].'"';
94517bd836SAndreas Gohr        if($data['height']) $R->doc .= ' height="'.$data['height'].'"';
95517bd836SAndreas Gohr        if($data['align'] == 'right') $ret .= ' align="right"';
96517bd836SAndreas Gohr        if($data['align'] == 'left')  $ret .= ' align="left"';
97517bd836SAndreas Gohr        $R->doc .= '/>';
98517bd836SAndreas Gohr    }
99517bd836SAndreas Gohr
10067682e69SAndreas Gohr    /**
10167682e69SAndreas Gohr     * Build the image URL using either our own generator or
10267682e69SAndreas Gohr     * the Google Chart API
10367682e69SAndreas Gohr     */
10467682e69SAndreas Gohr    function _imgurl($data){
10567682e69SAndreas Gohr        if($this->getConf('path')){
10667682e69SAndreas Gohr            // run graphviz on our own server
10767682e69SAndreas Gohr            $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data,'&');
10867682e69SAndreas Gohr        }else{
10967682e69SAndreas Gohr            // go through google
11067682e69SAndreas Gohr            $pass = array(
11167682e69SAndreas Gohr                'cht' => 'gv:'.$data['layout'],
11267682e69SAndreas Gohr                'chl' => $data['data'],
11367682e69SAndreas Gohr            );
11467682e69SAndreas Gohr            if($data['width'] && $data['height']){
11567682e69SAndreas Gohr                 $pass['chs'] = $data['width'].'x'.$data['height'];
11667682e69SAndreas Gohr            }
11767682e69SAndreas Gohr
11867682e69SAndreas Gohr            $img = 'http://chart.apis.google.com/chart?'.buildURLparams($pass,'&');
11967682e69SAndreas Gohr            $img = ml($img,array('w'=>$data['width'],'h'=>$data['height']));
12067682e69SAndreas Gohr        }
12167682e69SAndreas Gohr        return $img;
12267682e69SAndreas Gohr    }
123517bd836SAndreas Gohr
124517bd836SAndreas Gohr    /**
125*9d954370SAndreas Gohr     * Return path to created graphviz graph (local only)
126*9d954370SAndreas Gohr     */
127*9d954370SAndreas Gohr    function _imgfile($data){
128*9d954370SAndreas Gohr        $w = (int) $data['width'];
129*9d954370SAndreas Gohr        $h = (int) $data['height'];
130*9d954370SAndreas Gohr        unset($data['width']);
131*9d954370SAndreas Gohr        unset($data['height']);
132*9d954370SAndreas Gohr        unset($data['align']);
133*9d954370SAndreas Gohr
134*9d954370SAndreas Gohr        $cache = getcachename(join('x',array_values($data)),'graphviz.png');
135*9d954370SAndreas Gohr
136*9d954370SAndreas Gohr        // create the file if needed
137*9d954370SAndreas Gohr        if(!file_exists($cache)){
138*9d954370SAndreas Gohr            $this->_run($data,$cache);
139*9d954370SAndreas Gohr            clearstatcache();
140*9d954370SAndreas Gohr        }
141*9d954370SAndreas Gohr
142*9d954370SAndreas Gohr        // resized version
143*9d954370SAndreas Gohr        if($w) $cache = media_resize_image($cache,'png',$w,$h);
144*9d954370SAndreas Gohr
145*9d954370SAndreas Gohr        return $cache;
146*9d954370SAndreas Gohr    }
147*9d954370SAndreas Gohr
148*9d954370SAndreas Gohr    /**
149517bd836SAndreas Gohr     * Run the graphviz program
150517bd836SAndreas Gohr     */
151517bd836SAndreas Gohr    function _run($data,$cache) {
152903f28d7SAndreas Gohr        global $conf;
153903f28d7SAndreas Gohr
154517bd836SAndreas Gohr        $temp = tempnam($conf['tmpdir'],'graphviz_');
155517bd836SAndreas Gohr        io_saveFile($temp,$data['data']);
156903f28d7SAndreas Gohr
157517bd836SAndreas Gohr        $cmd  = $this->getConf('path');
158517bd836SAndreas Gohr        $cmd .= ' -Tpng';
159517bd836SAndreas Gohr        $cmd .= ' -K'.$data['layout'];
160517bd836SAndreas Gohr        $cmd .= ' -o'.escapeshellarg($cache); //output
161517bd836SAndreas Gohr        $cmd .= ' '.escapeshellarg($temp); //input
162903f28d7SAndreas Gohr
163517bd836SAndreas Gohr        exec($cmd, $output, $error);
164517bd836SAndreas Gohr        @unlink($temp);
165903f28d7SAndreas Gohr
166517bd836SAndreas Gohr        if ($error != 0){
167517bd836SAndreas Gohr            if($conf['debug']){
168517bd836SAndreas Gohr                dbglog(join("\n",$output),'graphviz command failed: '.$cmd);
169903f28d7SAndreas Gohr            }
170903f28d7SAndreas Gohr            return false;
171903f28d7SAndreas Gohr        }
172517bd836SAndreas Gohr        return true;
173903f28d7SAndreas Gohr    }
174903f28d7SAndreas Gohr
175903f28d7SAndreas Gohr}
176903f28d7SAndreas Gohr
177517bd836SAndreas Gohr
178517bd836SAndreas Gohr
179