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 * 86*eb42ed8aSAndreas Gohr * @todo latex support? 87903f28d7SAndreas Gohr */ 88517bd836SAndreas Gohr function render($format, &$R, $data) { 89*eb42ed8aSAndreas Gohr if($format == 'xhtml'){ 9067682e69SAndreas Gohr $img = $this->_imgurl($data); 91517bd836SAndreas Gohr $R->doc .= '<img src="'.$img.'" class="media'.$data['align'].'" alt=""'; 92517bd836SAndreas Gohr if($data['width']) $R->doc .= ' width="'.$data['width'].'"'; 93517bd836SAndreas Gohr if($data['height']) $R->doc .= ' height="'.$data['height'].'"'; 94517bd836SAndreas Gohr if($data['align'] == 'right') $ret .= ' align="right"'; 95517bd836SAndreas Gohr if($data['align'] == 'left') $ret .= ' align="left"'; 96517bd836SAndreas Gohr $R->doc .= '/>'; 97*eb42ed8aSAndreas Gohr return true; 98*eb42ed8aSAndreas Gohr }elseif($format == 'odt'){ 99*eb42ed8aSAndreas Gohr $src = $this->_imgfile($data); 100*eb42ed8aSAndreas Gohr $R->_odtAddImage($src,$data['width'],$data['height'],$data['align']); 101*eb42ed8aSAndreas Gohr return true; 102*eb42ed8aSAndreas Gohr } 103*eb42ed8aSAndreas Gohr return false; 104517bd836SAndreas Gohr } 105517bd836SAndreas Gohr 10667682e69SAndreas Gohr /** 10767682e69SAndreas Gohr * Build the image URL using either our own generator or 10867682e69SAndreas Gohr * the Google Chart API 10967682e69SAndreas Gohr */ 11067682e69SAndreas Gohr function _imgurl($data){ 11167682e69SAndreas Gohr if($this->getConf('path')){ 11267682e69SAndreas Gohr // run graphviz on our own server 11367682e69SAndreas Gohr $img = DOKU_BASE.'lib/plugins/graphviz/img.php?'.buildURLparams($data,'&'); 11467682e69SAndreas Gohr }else{ 11567682e69SAndreas Gohr // go through google 11667682e69SAndreas Gohr $pass = array( 11767682e69SAndreas Gohr 'cht' => 'gv:'.$data['layout'], 11867682e69SAndreas Gohr 'chl' => $data['data'], 11967682e69SAndreas Gohr ); 12067682e69SAndreas Gohr if($data['width'] && $data['height']){ 12167682e69SAndreas Gohr $pass['chs'] = $data['width'].'x'.$data['height']; 12267682e69SAndreas Gohr } 12367682e69SAndreas Gohr 12467682e69SAndreas Gohr $img = 'http://chart.apis.google.com/chart?'.buildURLparams($pass,'&'); 12567682e69SAndreas Gohr $img = ml($img,array('w'=>$data['width'],'h'=>$data['height'])); 12667682e69SAndreas Gohr } 12767682e69SAndreas Gohr return $img; 12867682e69SAndreas Gohr } 129517bd836SAndreas Gohr 130517bd836SAndreas Gohr /** 1319d954370SAndreas Gohr * Return path to created graphviz graph (local only) 1329d954370SAndreas Gohr */ 1339d954370SAndreas Gohr function _imgfile($data){ 1349d954370SAndreas Gohr $w = (int) $data['width']; 1359d954370SAndreas Gohr $h = (int) $data['height']; 1369d954370SAndreas Gohr unset($data['width']); 1379d954370SAndreas Gohr unset($data['height']); 1389d954370SAndreas Gohr unset($data['align']); 1399d954370SAndreas Gohr 1409d954370SAndreas Gohr $cache = getcachename(join('x',array_values($data)),'graphviz.png'); 1419d954370SAndreas Gohr 1429d954370SAndreas Gohr // create the file if needed 1439d954370SAndreas Gohr if(!file_exists($cache)){ 1449d954370SAndreas Gohr $this->_run($data,$cache); 1459d954370SAndreas Gohr clearstatcache(); 1469d954370SAndreas Gohr } 1479d954370SAndreas Gohr 1489d954370SAndreas Gohr // resized version 1499d954370SAndreas Gohr if($w) $cache = media_resize_image($cache,'png',$w,$h); 1509d954370SAndreas Gohr 1519d954370SAndreas Gohr return $cache; 1529d954370SAndreas Gohr } 1539d954370SAndreas Gohr 1549d954370SAndreas Gohr /** 155517bd836SAndreas Gohr * Run the graphviz program 156517bd836SAndreas Gohr */ 157517bd836SAndreas Gohr function _run($data,$cache) { 158903f28d7SAndreas Gohr global $conf; 159903f28d7SAndreas Gohr 160517bd836SAndreas Gohr $temp = tempnam($conf['tmpdir'],'graphviz_'); 161517bd836SAndreas Gohr io_saveFile($temp,$data['data']); 162903f28d7SAndreas Gohr 163517bd836SAndreas Gohr $cmd = $this->getConf('path'); 164517bd836SAndreas Gohr $cmd .= ' -Tpng'; 165517bd836SAndreas Gohr $cmd .= ' -K'.$data['layout']; 166517bd836SAndreas Gohr $cmd .= ' -o'.escapeshellarg($cache); //output 167517bd836SAndreas Gohr $cmd .= ' '.escapeshellarg($temp); //input 168903f28d7SAndreas Gohr 169517bd836SAndreas Gohr exec($cmd, $output, $error); 170517bd836SAndreas Gohr @unlink($temp); 171903f28d7SAndreas Gohr 172517bd836SAndreas Gohr if ($error != 0){ 173517bd836SAndreas Gohr if($conf['debug']){ 174517bd836SAndreas Gohr dbglog(join("\n",$output),'graphviz command failed: '.$cmd); 175903f28d7SAndreas Gohr } 176903f28d7SAndreas Gohr return false; 177903f28d7SAndreas Gohr } 178517bd836SAndreas Gohr return true; 179903f28d7SAndreas Gohr } 180903f28d7SAndreas Gohr 181903f28d7SAndreas Gohr} 182903f28d7SAndreas Gohr 183517bd836SAndreas Gohr 184517bd836SAndreas Gohr 185