<?php
/**
 * format plugin: Parses external command blocks
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Jason Grout <jason-doku@creativetrax.com>
 * @version    2007-02-22
 * heavily based on the graphviz plugin (with the dokutexit extensions) and the gnuplot plugin.
 */

if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
require_once(DOKU_INC.'inc/init.php');
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
require_once(DOKU_PLUGIN.'syntax.php');


/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_format extends DokuWiki_Syntax_Plugin {


  function getInfo(){
    return array(
		 'author' => 'Jason Grout',
		 'email'  => 'jason-doku@creativetrax.com',
		 'date'   => '2007-02-22',
		 'name'   => 'format Plugin',
		 'desc'   => 'Sends text to external program',
		 'url'    => 'https://www.dokuwiki.org/plugin:format',
		 );
  }

  /**
   * What kind of syntax are we?
   */
  function getType(){
    return 'protected';
  }
   
  /**
   * Where to sort in?
   */ 
  function getSort(){
    return 100;
  }


  /**
   * Connect pattern to lexer
   */
  function connectTo($mode) {
    $this->Lexer->addEntryPattern('<format(?=.*?</format>)',$mode,'plugin_format');
  }

  function postConnect() {
    $this->Lexer->addExitPattern('</format>','plugin_format');
  }

  /**
   * Handle the match
   */


  function handle($match, $state, $pos) {
    global $conf;
    if ( $state == DOKU_LEXER_UNMATCHED ) {
      $matches = preg_split('/>/u',$match,2);
      $matches[0] = trim($matches[0]);
      if ( trim($matches[0]) == '' ) {
	$matches[0] = NULL;
      }
      // $matches[0] is the format name
      // $matches[1] is the text inside the format block
      return array($matches[1],$matches[0]);
    }
    return TRUE;
  }
  /**
   * Create output
   */
  function render($mode, &$renderer, $data) {
    global $conf;
    $program = $data[1];
    $text = $data[0];
    if(($mode == 'xhtml' || $mode == 'latex' )
       && strlen($text) > 1 
       && strlen($program) > 0) {
      
      $config = $this->getConf($program);
      if(!$config || !$config[$mode]) {
	$renderer->doc .='** "'.$renderer->_xmlEntities($program)
	  .'" format not configured for '.$mode.' output**';
	return true;
      }

      if($config[$mode]['ext']=='multipart') {
	$multipart = true;
      } else {
	$multipart = false;
      }

      // TODO: make directory mediadir/format/program/namespace/page
      $dirname = $conf['mediadir'] . '/format/' . $program;
      if( !is_dir($dirname) ) 
	io_mkdir_p($dirname); //Using dokuwiki framework
      
      $hashname = md5(serialize($data)).'.'.$config[$mode]['ext'];
      
      $medianame = $dirname.'/'.$hashname;
      $medians = ":format:".$program.":";
      if($multipart) {
	$medians = $medians.$hashname.":";
      }
      
      if($multipart) {
	$outfilename = $medianame.'/home.txt';
      } else {
	$outfilename = '';
      }

      if ( ! is_readable($medianame) ) {
	if($multipart) { //create directory
	  io_mkdir_p($medianame); 
	}
	if ($this->createMedia($medianame, $outfilename, $multipart,
			       $text, $program, $mode)===false) {
	  $renderer->doc .= '**ERROR RENDERING '.$config['name'].'**';

	  // TODO: Make this portable
	  `rm -rf $medianame`;

	  return true;
	}
      }

      // $medianame is the name of the media file if not multipart
      // $medianame is the name of the media directory if multipart
      // $medians is the namespace in which the media file(s) live.
      // if multipart, then it is $dirname:$medianame, if not, then it is $dirname

      if($multipart) {
	// replace the @DOKUMEDIA:name:filename@ with a call to internalmedia
	/*        $renderer->doc .= "<pre>".preg_replace('/@DOKUMEDIA:([^:]*):([^@]*)@/e',
				       "'</pre>'.\$renderer->internalmedia(\$medians.'$2', '$1').'<pre>'",
				       $renderer->_xmlEntities(file_get_contents($outfilename)))."</pre>";
	*/
      } else {
	
	switch($mode) {
	case 'xhtml':
	  $renderer->doc .= $renderer->internalmedia($medians.$hashname,
						     $config['name']); 
	  break;
	case 'latex':
	  $renderer->doc .= "\\begin{figure}[h]\n";
	  $renderer->doc .= "\t\\begin{center}\n";
	  $renderer->doc .= "\t\t\\includegraphics{";
	  $renderer->doc .= $medianame;
	  $renderer->doc .= "}\n";
	  $renderer->doc .= "\t\\end{center}\n";
	  $renderer->doc .= "\\end{figure}\n";
	  break;
	}
      }
      
      
      return true;
    }
    
    return false;
  }

  
  
  function createMedia($medianame, $outfilename, $multipart, &$text, $program, $mode='xhtml') {
    global $conf;
    $config = $this->getConf($program);
    if(!$config || !$config[$mode]) return false;
    

    
    $tmpinput = tempnam($this->getConf('tmpdir'), "dokuwiki.format");
    $pre = str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
		       array($tmpinput, $outfilename, $medianame),
		       $config[$mode]['pre']);
    $post = str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
			array($tmpinput, $outfilename,$medianame),
		       $config[$mode]['post']);

    $wrappeddata = $pre.$text.$post;
    //$this->printpre($wrappeddata);
    io_saveFile($tmpinput, $wrappeddata); //Using dokuwiki framework

    // TODO: do I need to initialize these variables before passing them to exec?
    $output=array();
    $retval='';

    // Replace the variable strings
    $command=str_replace(array('@INFILE@','@OUTFILE@','@MEDIAFILE@'),
			 array($tmpinput, $outfilename, $medianame),
			 $config[$mode]['command'])
    //$this->printpre($command);
    exec($command,$output,$retval);
    //$this->printpre(print_r($output,true));
    unlink($tmpinput);
    return $retval;
  }
  function printpre($data) {
    print("<pre>".$data."</pre>");
  }

}

?>