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 52 $return = array( 53 'data' => '', 54 'width' => 0, 55 'height' => 0, 56 'layout' => 'dot', 57 'align' => '', 58 'version' => $info['date'], //force rebuild of images on update 59 ); 60 61 // prepare input 62 $lines = explode("\n",$match); 63 $conf = array_shift($lines); 64 array_pop($lines); 65 66 // match config options 67 if(preg_match('/\b(left|center|right)\b/i',$conf,$match)) $return['align'] = $match[1]; 68 if(preg_match('/\b(\d+)x(\d+)\b/',$conf,$match)){ 69 $return['width'] = $match[1]; 70 $return['height'] = $match[2]; 71 } 72 if(preg_match('/\b(dot|neato|twopi|circo|fdp)\b/i',$conf,$match)){ 73 $return['layout'] = strtolower($match[1]); 74 } 75 if(preg_match('/\bwidth=([0-9]+)\b/i', $conf,$match)) $return['width'] = $match[1]; 76 if(preg_match('/\bheight=([0-9]+)\b/i', $conf,$match)) $return['height'] = $match[1]; 77 78 $return['data'] = join("\n",$lines); 79 80 return $return; 81 } 82 83 /** 84 * Create output 85 * 86 * @todo latex and ODT support 87 */ 88 function render($format, &$R, $data) { 89 if($format != 'xhtml') return; 90 91 $img = $this->_imgurl($data); 92 $R->doc .= '<img src="'.$img.'" class="media'.$data['align'].'" alt=""'; 93 if($data['width']) $R->doc .= ' width="'.$data['width'].'"'; 94 if($data['height']) $R->doc .= ' height="'.$data['height'].'"'; 95 if($data['align'] == 'right') $ret .= ' align="right"'; 96 if($data['align'] == 'left') $ret .= ' align="left"'; 97 $R->doc .= '/>'; 98 } 99 100 /** 101 * Build the image URL using either our own generator or 102 * the Google Chart API 103 */ 104 function _imgurl($data){ 105 if($this->getConf('path')){ 106 // run graphviz on our own server 107 $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data,'&'); 108 }else{ 109 // go through google 110 $pass = array( 111 'cht' => 'gv:'.$data['layout'], 112 'chl' => $data['data'], 113 ); 114 if($data['width'] && $data['height']){ 115 $pass['chs'] = $data['width'].'x'.$data['height']; 116 } 117 118 $img = 'http://chart.apis.google.com/chart?'.buildURLparams($pass,'&'); 119 $img = ml($img,array('w'=>$data['width'],'h'=>$data['height'])); 120 } 121 return $img; 122 } 123 124 /** 125 * Run the graphviz program 126 */ 127 function _run($data,$cache) { 128 global $conf; 129 130 $temp = tempnam($conf['tmpdir'],'graphviz_'); 131 io_saveFile($temp,$data['data']); 132 133 $cmd = $this->getConf('path'); 134 $cmd .= ' -Tpng'; 135 $cmd .= ' -K'.$data['layout']; 136 $cmd .= ' -o'.escapeshellarg($cache); //output 137 $cmd .= ' '.escapeshellarg($temp); //input 138 139 exec($cmd, $output, $error); 140 @unlink($temp); 141 142 if ($error != 0){ 143 if($conf['debug']){ 144 dbglog(join("\n",$output),'graphviz command failed: '.$cmd); 145 } 146 return false; 147 } 148 return true; 149 } 150 151} 152 153 154 155