<?php
/**
 * Prolog plug-in : Rule-based System for Groupware.
 * 
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
 * @author     Paweł Kupka <pawel.kupka@gmail.com>
 */
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die(); 
if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins');
if(!defined('DOKU_PAGES')) define('DOKU_PAGES',DOKU_INC.'data/pages');
require_once(DOKU_INC . 'inc/parserutils.php');
require_once(DOKU_PLUGIN.'syntax.php');
require_once('prolog_tag.php');
require_once('attribute_include.php');
require_once('attribute_options.php');
require_once('attribute_maxruntime.php');

/**
 * All DokuWiki plugins to extend the parser/rendering mechanism
 * need to inherit from this class
 */
class syntax_plugin_prolog extends DokuWiki_Syntax_Plugin {
		
	var $prologTag;
	var $attrMaxRunTime;
	var $attrInclude;
	var $attrOptions;
		
	/**
	 * Constructor
	 */
	function syntax_plugin_prolog()
	{
		$this->prologTag = & new PrologTag();
		$this->attrInclude = & new AttributeInclude();
		$this->attrOptions = & new AttributeOptions();
		$this->attrMaxRunTime = & new AttributeMaxRunTime();
	}
	
	/**
	 * Returns the information about syntax prolog plug-in
	 * @return array information
	 */
	function getInfo()
	{
		return array
					 (
						 'author' => 'Paweł Kupka',
						 'email'  => 'pawel.kupka@gmail.com',
						 'date'   => '2008-05-02',
						 'name'   => 'Syntax prolog plug-in',
						 'desc'   => 'Rule-based System for Groupware.',
						 'url'    => 'https://ai.ia.agh.edu.pl'
					 );
	}
 
	/**
	 * Defines to which type of syntax the plug-in belongs
	 * @return string mode type
	 */
	function getType()
	{ 
		return 'protected';
	}

	/**
	 * Tells the parser which other syntax modes are permitted inside the plug-in
	 * @return array allowed mode types
	 */
	function getAllowedTypes() 
	{ 
		return array();
	} 
		
	/**
	 * Defines how this syntax is handled regarding paragraphs
	 * @return string kind of the paragraph's operation
	 */
	function getPType()
	{
		return 'normal';
	}

	/**
	 * Returns sort number
	 * @return integer sort number
	 */
	function getSort()
	{ 
		return 205; 
	}
		
	/**
	 * Registers the enter pattern of the prolog syntax plug-in
	 * @param string syntax mode type
	 */
	function connectTo($mode) 
	{ 
		$this->Lexer->addEntryPattern('<prolog.*?>(?=.*?</prolog>)',$mode,'plugin_prolog');
	}
			
	/**
	 * Registers the exit pattern of the prolog syntax plug-in
	 */
	function postConnect() 
	{ 
		$this->Lexer->addExitPattern('</prolog>', 'plugin_prolog');
	}
 
 
	/**
	 * Handles the match
	 */
	function handle($match, $state, $pos, &$handler)
	{
		switch ($state) 
		{
			case DOKU_LEXER_ENTER :
				$_SESSION['prolog']['maxruntimeValue'] = $this->attrMaxRunTime->getAttributeValue($match);
				$_SESSION['prolog']['includeValue'] = $this->attrInclude->getAttributeValue($match);
				$_SESSION['prolog']['optionsValue'] = $this->attrOptions->getAttributeValue($match);
				return;
			case DOKU_LEXER_UNMATCHED :  
				if(isset($_SESSION['prolog']['match']))
					$_SESSION['prolog']['match'] .= $match."\n";
				else
					$_SESSION['prolog']['match'] = $match."\n";								
				return;
			case DOKU_LEXER_EXIT :
				$maxRunTime = $_SESSION['prolog']['maxruntimeValue'];
				$options = $this->attrOptions->getOptions($_SESSION['prolog']['optionsValue']);
				$includedFilesList = $this->attrInclude->getFilesList($_SESSION['prolog']['includeValue']);
				$prologCode = $this->attrInclude->readCode($includedFilesList) . $_SESSION['prolog']['match'];
				unset($_SESSION['prolog']);
				return array($state, array($prologCode, $maxRunTime, $includedFilesList, $options));
		}
		return array();
	}
 
	/**
	 * Creates output
	 */
	function render($mode, &$renderer, $data) 
	{
		if($mode == 'xhtml')
		{
			list($state, $match) = $data;
			switch ($state) 
			{
				case DOKU_LEXER_ENTER : 
					break;
				case DOKU_LEXER_UNMATCHED :  							
					break;
				case DOKU_LEXER_EXIT :  
					list($prologCode, $maxRunTime, $includedFilesList, $options) = $match;
					$executedCode = $this->prologTag->execute($prologCode, $maxRunTime);
					foreach($options as $option) 
					{
						$this->attrOptions->authorizeOption($option);
						$renderer->doc .= $this->attrOptions->handleOptionDebug($executedCode[1]);
						$renderer->doc .= $this->attrOptions->handleOptionFiles($includedFilesList);
						$renderer->doc .= $this->attrOptions->handleOptionSource(str_replace("\n",'<br />',$prologCode));
					}
					$instructions = p_get_instructions($executedCode[0]);
					foreach($instructions as $instruction) 
						call_user_func_array(array($renderer, $instruction[0]),$instruction[1]);
					break;
			}
			return true;
		}
		return false;
	}
}
?>