1<?php 2/** 3 * visrep-Plugin: Parses visrep-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 * @author Ionut Stoica <stoica.ionut@gmail.com> 9 */ 10 11 12if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/'); 13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 14require_once(DOKU_PLUGIN.'syntax.php'); 15 16class syntax_plugin_visrep extends DokuWiki_Syntax_Plugin { 17 18 /** 19 * What about paragraphs? 20 */ 21 function getPType(){ 22 return 'block'; 23 } 24 25 /** 26 * What kind of syntax are we? 27 */ 28 function getType(){ 29 return 'substition'; 30 } 31 32 /** 33 * Where to sort in? 34 */ 35 function getSort(){ 36 return 200; 37 } 38 39 /** 40 * Connect pattern to lexer 41 */ 42 function connectTo($mode) { 43 $this->Lexer->addSpecialPattern('<visrep.*?>\n.*?\n</visrep>', $mode, 'plugin_visrep'); 44 } 45 46 /** 47 * Handle the match 48 */ 49 function handle($match, $state, $pos, &$handler) { 50 51 $info = $this->getInfo(); 52 $xml = sprintf("<?xml version=\"1.0\" encoding=\"utf-8\"?>%s", $match); 53 54 $dom = simplexml_load_string($xml); 55 $dat = (array)$dom->attributes(); 56 $attrs = empty($dat['@attributes']) || !is_array($dat['@attributes']) ? array() : $dat['@attributes']; 57 58 $defaults = array( 59 'theme' => NULL, // napking | serious 60 'width' => 0, 61 'height' => 0, 62 'align' => '', 63 'data-layout' => NULL, // dot|neato|twopi|circo|fdp 64 'data-engine' => strtolower(empty($attrs['data-engine']) ? 'unknown' : $attrs['data-engine']), 65 'data-version' => $info['date'], 66 'md5' => md5($match), 67 ); 68 $input = trim((string)$dom); 69 $return = array_merge( 70 $defaults, 71 $attrs 72 ); 73 74 // store input for later use 75 io_saveFile($this->_cachename($return, 'txt'), $this->_data($return, $input)); 76 77 return $return; 78 } 79 80 function _data($attrs, $input) { 81 $data = $input; 82 switch ($attrs['data-engine']) { 83 case 'blockdiag': 84 case 'seqdiag': 85 case 'actdiag': 86 case 'nwdiag': 87 case 'rackdiag': 88 case 'packetdiag': 89 $data = sprintf("%s {\n%s\n}", $attrs['data-engine'], $data); 90 break; 91 default: 92 $data = preg_replace('~(.*)' . preg_quote('}', '~') . '~', '$1' . "\nsize=\"%s,%s\"; resolution=72;\n}", $data, 1); 93 break; 94 } 95 return $data; 96 } 97 98 /** 99 * Cache file is based on parameters that influence the result image 100 */ 101 function _cachename($data, $ext) { 102 return getcachename(join('x', array_values($data)),'.visrep.'.$ext); 103 } 104 105 /** 106 * Create output 107 */ 108 function render($format, &$R, $data) { 109 if($format == 'xhtml') { 110 $attrs = array(); 111 112 if(is_a($R,'renderer_plugin_dw2pdf')){ 113 $url = 'dw2pdf://'.$this->_imgfile($data); 114 } else { 115 $url = DOKU_BASE.'lib/plugins/visrep/img.php?'.buildURLparams($data); 116 } 117 118 foreach ($data as $k=>$v) { 119 if ($k == 'md5') continue; 120 if (is_null($v) || strlen($v) == 0) continue; 121 if (in_array($k, array('width', 'height'))) continue; 122 $attrs[] = sprintf('%s = "%s"', htmlspecialchars($k, ENT_QUOTES, 'UTF-8'), htmlspecialchars($v, ENT_QUOTES, 'UTF-8')); 123 } 124 125 $attrs[] = sprintf('src = "%s"', $url); 126 $code = sprintf('<img %s alt="" class="dokuwiki-visrep-image"/>', implode(' ', $attrs)); 127 128 129 $R->doc .= $w_start . $code . $w_end; 130 return true; 131 } elseif($format == 'odt'){ 132 $src = $this->_imgfile($data); 133 $R->_odtAddImage($src, $data['width'], $data['height'], $data['align']); 134 return true; 135 } 136 return false; 137 } 138 139 /** 140 * Return path to the rendered image on our local system 141 */ 142 function _imgfile($data) { 143 $cache = $this->_cachename($data, 'png'); 144 // create the file if needed 145 if (!file_exists($cache)) { 146 $in = $this->_cachename($data, 'txt'); 147 $ok = $this->_run($data, $in, $cache); 148 if(!$ok) return false; 149 clearstatcache(); 150 } 151 152 // resized version 153 //if ($data['width']){ 154 // $cache = media_resize_image($cache, 'png', $data['width'], $data['height']); 155 //} 156 157 // something went wrong, we're missing the file 158 if(!file_exists($cache)) return false; 159 return $cache; 160 } 161 162 /** 163 * Run the visrep program 164 */ 165 function _run($data,$in,$out) { 166 global $conf; 167 168 $loc = 'path_'.$data['data-engine']; 169 $cmd = $this->getConf($loc); 170 171 if ($this->_isBlockDiag($data['data-engine'])) { 172 if (!empty($data['width']) && !empty($data['height'])) { 173 $cmd .= sprintf(' --size=%dx%d', $data['width'], $data['height']); 174 } 175 // $cmd .= ' -a'; 176 $cmd .= ' -o '.str_ireplace('/', DIRECTORY_SEPARATOR, escapeshellarg($out)); 177 $cmd .= ' '.str_ireplace('/', DIRECTORY_SEPARATOR, escapeshellarg($in)); 178 } 179 180 if ($data['data-engine'] == 'graphviz') { 181 $cmd .= ' -Tpng'; 182 if (isset($data['layout']) && in_array($data['layout'], array('dot', 'neato', 'fdp', 'twopi', 'circo'))) { 183 $cmd .= ' -K'.$data['layout']; 184 } 185 $cmd .= ' -o'.str_ireplace('/', DIRECTORY_SEPARATOR, escapeshellarg($out)); 186 $cmd .= ' '.str_ireplace('/', DIRECTORY_SEPARATOR, escapeshellarg($in)); 187 } 188 189 exec($cmd, $output, $error); 190 191 if ($error != 0){ 192 if($conf['debug']){ 193 dbglog(join("\n",$output),'visrep command failed: '.$cmd); 194 } 195 return false; 196 } 197 198 return true; 199 } 200 201 202 function _isBlockDiag($engine) { 203 return in_array($engine, array('seqdiag', 'blockdiag', 'actdiag', 'nwdiag', 'rackdiag', 'packetdiag')); 204 } 205 206} 207 208 209 210