1<?php
2/**
3 * format plugin: Parses external command blocks
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Jason Grout <jason-doku@creativetrax.com>
7 * @version    2007-02-22
8 * heavily based on the graphviz plugin (with the dokutexit extensions) and the gnuplot plugin.
9 */
10
11if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
12require_once(DOKU_INC.'inc/init.php');
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14require_once(DOKU_PLUGIN.'syntax.php');
15
16
17/**
18 * All DokuWiki plugins to extend the parser/rendering mechanism
19 * need to inherit from this class
20 */
21class syntax_plugin_format extends DokuWiki_Syntax_Plugin {
22
23
24  function getInfo(){
25    return array(
26		 'author' => 'Jason Grout',
27		 'email'  => 'jason-doku@creativetrax.com',
28		 'date'   => '2007-02-22',
29		 'name'   => 'format Plugin',
30		 'desc'   => 'Sends text to external program',
31		 'url'    => 'https://www.dokuwiki.org/plugin:format',
32		 );
33  }
34
35  /**
36   * What kind of syntax are we?
37   */
38  function getType(){
39    return 'protected';
40  }
41
42  /**
43   * Where to sort in?
44   */
45  function getSort(){
46    return 100;
47  }
48
49
50  /**
51   * Connect pattern to lexer
52   */
53  function connectTo($mode) {
54    $this->Lexer->addEntryPattern('<format(?=.*?</format>)',$mode,'plugin_format');
55  }
56
57  function postConnect() {
58    $this->Lexer->addExitPattern('</format>','plugin_format');
59  }
60
61  /**
62   * Handle the match
63   */
64
65
66  function handle($match, $state, $pos) {
67    global $conf;
68    if ( $state == DOKU_LEXER_UNMATCHED ) {
69      $matches = preg_split('/>/u',$match,2);
70      $matches[0] = trim($matches[0]);
71      if ( trim($matches[0]) == '' ) {
72	$matches[0] = NULL;
73      }
74      // $matches[0] is the format name
75      // $matches[1] is the text inside the format block
76      return array($matches[1],$matches[0]);
77    }
78    return TRUE;
79  }
80  /**
81   * Create output
82   */
83  function render($mode, &$renderer, $data) {
84    global $conf;
85    $program = $data[1];
86    $text = $data[0];
87    if(($mode == 'xhtml' || $mode == 'latex' )
88       && strlen($text) > 1
89       && strlen($program) > 0) {
90
91      $config = $this->getConf($program);
92      if(!$config || !$config[$mode]) {
93	$renderer->doc .='** "'.$renderer->_xmlEntities($program)
94	  .'" format not configured for '.$mode.' output**';
95	return true;
96      }
97
98      if($config[$mode]['ext']=='multipart') {
99	$multipart = true;
100      } else {
101	$multipart = false;
102      }
103
104      // TODO: make directory mediadir/format/program/namespace/page
105      $dirname = $conf['mediadir'] . '/format/' . $program;
106      if( !is_dir($dirname) )
107	io_mkdir_p($dirname); //Using dokuwiki framework
108
109      $hashname = md5(serialize($data)).'.'.$config[$mode]['ext'];
110
111      $medianame = $dirname.'/'.$hashname;
112      $medians = ":format:".$program.":";
113      if($multipart) {
114	$medians = $medians.$hashname.":";
115      }
116
117      if($multipart) {
118	$outfilename = $medianame.'/home.txt';
119      } else {
120	$outfilename = '';
121      }
122
123      if ( ! is_readable($medianame) ) {
124	if($multipart) { //create directory
125	  io_mkdir_p($medianame);
126	}
127	if ($this->createMedia($medianame, $outfilename, $multipart,
128			       $text, $program, $mode)===false) {
129	  $renderer->doc .= '**ERROR RENDERING '.$config['name'].'**';
130
131	  // TODO: Make this portable
132	  `rm -rf $medianame`;
133
134	  return true;
135	}
136      }
137
138      // $medianame is the name of the media file if not multipart
139      // $medianame is the name of the media directory if multipart
140      // $medians is the namespace in which the media file(s) live.
141      // if multipart, then it is $dirname:$medianame, if not, then it is $dirname
142
143      if($multipart) {
144	// replace the @DOKUMEDIA:name:filename@ with a call to internalmedia
145	/*        $renderer->doc .= "<pre>".preg_replace('/@DOKUMEDIA:([^:]*):([^@]*)@/e',
146				       "'</pre>'.\$renderer->internalmedia(\$medians.'$2', '$1').'<pre>'",
147				       $renderer->_xmlEntities(file_get_contents($outfilename)))."</pre>";
148	*/
149      } else {
150
151	switch($mode) {
152	case 'xhtml':
153	  $renderer->doc .= $renderer->internalmedia($medians.$hashname,
154						     $config['name']);
155	  break;
156	case 'latex':
157	  $renderer->doc .= "\\begin{figure}[h]\n";
158	  $renderer->doc .= "\t\\begin{center}\n";
159	  $renderer->doc .= "\t\t\\includegraphics{";
160	  $renderer->doc .= $medianame;
161	  $renderer->doc .= "}\n";
162	  $renderer->doc .= "\t\\end{center}\n";
163	  $renderer->doc .= "\\end{figure}\n";
164	  break;
165	}
166      }
167
168
169      return true;
170    }
171
172    return false;
173  }
174
175
176
177  function createMedia($medianame, $outfilename, $multipart, &$text, $program, $mode='xhtml') {
178    global $conf;
179    $config = $this->getConf($program);
180    if(!$config || !$config[$mode]) return false;
181
182
183
184    $tmpinput = tempnam($this->getConf('tmpdir'), "dokuwiki.format");
185    $pre = str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
186		       array($tmpinput, $outfilename, $medianame),
187		       $config[$mode]['pre']);
188    $post = str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
189			array($tmpinput, $outfilename,$medianame),
190		       $config[$mode]['post']);
191
192    $wrappeddata = $pre.$text.$post;
193    //$this->printpre($wrappeddata);
194    io_saveFile($tmpinput, $wrappeddata); //Using dokuwiki framework
195
196    // TODO: do I need to initialize these variables before passing them to exec?
197    $output=array();
198    $retval='';
199
200    // Replace the variable strings
201    $command=str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
202			 array($tmpinput, $outfilename, $medianame),
203			 $config[$mode]['command'])
204    //$this->printpre($command);
205    exec($command,$output,$retval);
206    //$this->printpre(print_r($output,true));
207    unlink($tmpinput);
208    return $retval;
209  }
210  function printpre($data) {
211    print("<pre>".$data."</pre>");
212  }
213
214}
215
216?>