<?php
/*
EasyGUI XP is free software released under the terms of the following BSD license.

Copyright (c) 2005,2006 Gaetan Lauff (glauff@plansoft.de)
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer. 

- Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution.

- Neither the name of the developer nor the names of its contributors may 
be used to endorse or promote products derived from this software without 
specific prior written permission. 

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
 * EasyGUI XP Template Engine
 *
 * Template Engine sets all Values in Template before Transformation
 * So we can use whatever template engine we'd like for our projects
 * To make this clear:
 * A Template engine uses no kind of XML Parser.
 * This is just to replace various constructs in file by other constructs
 * 
 *
 * @author Gaetan Lauff <glauff@plansoft.de>
 * @version	$Id: class.ek_template_engine.php 44 2006-02-28 13:40:01Z glauff $
 * @package template.engine
 */
class EK_TemplateEngine
{
	/**
	 * @var string
	 */ 
	var $template;
	
	/**
	 * @var	object
	 */
	var $ekObject;
	
	/**
	 * Template Object
	 *
	 * @var object
	 */
	var $tpl;
	
	/**
	 * EK_TemplateEngine Constructor
	 * 
	 * @param 	reference	&$ekObject	EK_webapp Object
	 * @return	void
	 *
	 * @access 	public
	 */
	function EK_TemplateEngine( &$ekObject, &$tpl )
	{
		$this->ekObject =& $ekObject;
		$this->tpl		=& $tpl;
		
		EK_Common::getRequiredClasses( EK_ROOT . '/lib/template/engine/components/' );
		
		if ( defined( 'EK_ENGINE_COMPLIB' ) ) {
			EK_Common::getRequiredClasses( EK_ENGINE_COMPLIB );
		}
	}
	
	/**
	 * Fetch Method
	 *
	 * This method is called by the framework.
	 * If you implement your own Template Engine make sure to overwrite this method.
	 *
	 * @return 	string	The treated Template
	 */
	function fetch ()
	{
		$path 		= $this->tpl->getTplPath();
		$template 	= $this->tpl->getTemplate();
		
		preg_match_all("/~#include(.*)~/", $template, $imports, PREG_PATTERN_ORDER);
		
		foreach($imports[1] as $key => $fileName) {
			$fileName = $path . '/' .trim($fileName);
			
			if (!file_exists($fileName)) {
				trigger_error("Include File: ".$fileName." not found ", E_USER_ERROR);
			}
			
			if (EK_Common::isEKFile($fileName)) {
				$file 		= file_get_contents($fileName);
				$template 	= str_replace($imports[0][$key], $file, $template);
			} else {
				$tag 		= "<include filename=\"".$fileName."\" />\n";
				$template 	= str_replace($imports[0][$key], $tag, $template);
			}
		}
		
		if ( APPMODE == 'ek_cdrom' ) {
			return $this->replaceAliases( $template );
		}
		
		if ( APPMODE == 'ek_internet' ) {
			$template = $this->replaceAliases( $template );
		}
		
		return $this->assignValues( $template );
	}
	
	/**
	 * Replaces all Aliases
	 *
	 * Here all the Aliases defined in the webapp.ekw file are replaced by their
	 * relative path to the server.
	 *
	 * @param 	string	$template
	 * @return 	string	The Template String with replaced Aliases if any where found
	 *
	 * @access 	private
	 */
	function replaceAliases ( $template )
	{
		if ( is_array( $this->ekObject->config ) && isset( $this->ekObject->config['ALIASES'] ) ) {
			$aliases = $this->ekObject->config['ALIASES'];
			
			foreach( $aliases as $alias => $path ) {
				$template = str_replace( "/" . $alias . "/", $path . "/", $template );
			}
		} else {
			$aliases2 = array();
			$uiSettings = $this->ekObject->config->getElementsByTagName( 'UserInterface');
			
			if ( !is_null( $uiSettings ) ) {
				$paths 	= $this->ekObject->config->getElementsByTagName( 'Paths', $uiSettings[0] );
				$aliases1 = EK_SimpleXML::childNodes( $paths );
			}
		
			$uiAliases = $this->ekObject->config->getElementsByTagName( 'Aliases' );
			
			if ( !is_null( $uiAliases ) ) {
				$aliases2 = EK_SimpleXML::childNodes( $uiAliases[0] );
			}
			
			$aliases = array_merge( $aliases1, $aliases2 );
			
			foreach( $aliases as $node ) {
				$path = strtolower(str_replace('\\', '/', EK_SimpleXML::getAttribute( $node, 'path' ) ) );
				$path = str_replace( '$progdir$', APPPATH, $path );
				//$path = str_replace( '$temp$', $_ENV['TEMP'], $path );
				
				$path = str_replace( APPPATH , '', $path );
				$path = str_replace( $_SERVER['DOCUMENT_ROOT'], '', $path );
				
				$pos = strpos( $path, '/' );
				
				if ( $pos !== false && $pos == 0) {
					$path = substr( $path, 1, strlen($path));
				}
				
				$pos = strrpos( $path, '/' );
				
				if ( !$pos || ( $pos !== false && $pos != ( strlen( $path ) - 1 ) ) ) {
					$path .= '/';
				}
				
				$path = "./" . $path;
				
				$alias = EK_SimpleXML::getAttribute( $node, 'alias' );
				
				if (!empty($alias)) {
					$alias = "/" . str_replace( "/", "",  $alias ) . "/" ;
					$template = str_replace( $alias, $path, $template );
				}
				
				$name = EK_SimpleXML::getAttribute( $node, 'name' );
				
				if ( !empty($name) ) {
					$name = "/" . str_replace( "/", "", $name ) . "/";
					$template = str_replace( $name, $path, $template );
				}
			}
		}
		
		return $template;
	}
	
	/**
	 * Translate all Texts
	 *
	 * This method replaces all String Placehoders defined in the Template by their
	 * Value in the Database.
	 *
	 * @param 	string 	$template	The Template String
	 * @return 	string	The Template String with replaced Texts, if any were defined.
	 *
	 * @access 	private
	 */
	function translate( $template )
	{
		if (!isset($this->ekObject->dictionary)) {
			return;
		}
			
		preg_match_all('/\$([^\$]+)\$/', $template, $texts, PREG_PATTERN_ORDER);
		
		foreach($texts[1] as $id) {
			$text = $this->ekObject->getText( $id );
			$text = html_entity_decode($text);
			$text = preg_replace( '~&#x([0-9a-f]+);~ei', 'chr(hexdec("\\1"))', $text );		
			$text = preg_replace( '~&#([0-9]+);~e', 'chr(\\1)', $text );
	
			$text = htmlspecialchars( nl2br( $text ) );
			
			$template = str_replace("$".$id."$", $text, $template);	
		}

		return $template;
	}
	
	/**
	 * Assigns values to Template
	 *
	 * This method assigns all values to their Placeholders
	 *
	 * @param	string	Template 	The Template String
	 * @return 	string	The Template String with all Placeholders replaced by their values
	 *
	 * @access 	private
	 */
	function assignValues( $template )
	{
		preg_match_all('/{\$([^}\"]+)}/U', $template, $phpvalues, PREG_PATTERN_ORDER);
		preg_match_all('/\%([^\%\"]+)\%/U', $template, $values, PREG_PATTERN_ORDER);
		preg_match_all('/\"(.+)\%([^\%\"]+)\%(.+)\"/U', $template, $innervalues, PREG_PATTERN_ORDER);
		preg_match_all('/\"@([^@\$)\"]+)@\"/U', $template, $queries, PREG_PATTERN_ORDER);
		preg_match_all('/\"(.*){@([^@}\"]+)@}(.*)\"/U', $template, $innerqueries, PREG_PATTERN_ORDER);
		preg_match_all('/\"#([^#\"]+)#\"/U', $template, $components1, PREG_PATTERN_ORDER);
		preg_match_all('/~([^~]+)~/U', $template, $components2, PREG_PATTERN_ORDER);
		
		//print_r($queries1);
		
		foreach ( $phpvalues[1] as $var ) {
			$value = $this->ekObject->getAppValue( $var );
		
			if ( is_null( $value ) ) {
				$value = $this->tpl->getValue( $var );
			}
			
			$template = str_replace("{\$".$var."}", $value, $template);
		}
		
		foreach( $values[1] as $id ) {
			$value = $this->ekObject->getValue( $id );
			
			if ( is_null( $value ) ) {
				$value = $this->tpl->getValue( $id );
			}
			
			$template = str_replace("%".$id."%", $value, $template);			
		}
		
		foreach ( $innervalues[2] as $id ) {
			$value = $this->ekObject->getValue( $id );
			$template = str_replace("%".$id."%", $value, $template);
		}
		
		foreach ( $queries[1] as $query ) {
			$value = $this->ekObject->getValueFromQuery( $query );
			$template = str_replace("@" . $query . "@", $value, $template );
		}

		foreach ( $innerqueries[2] as $query ) {
			$value = $this->ekObject->getValueFromQuery( $query );
			$template = str_replace("{@" . $query . "@}", $value, $template );
		}
		
		foreach( $components1[1] as $componentId) {
			$component = $this->getComponent( $componentId );
			$template = str_replace("#" . $componentId . "#", $component, $template );
		}
		
		foreach( $components2[1] as $componentId) {
			$component = $this->getComponent( $componentId );
			$template = str_replace("~" . $componentId . "~", $component, $template );
		}
				
		if (isset($this->ekObject->dictionary)) {
			$template = $this->translate( $template );
		}
			
		return $template;
	}
	
	/**
	 * Used to render a specific component
	 *
	 * @param	string	$id
	 *
	 * @return 	string	Component
	 *
	 * @access	private
	 */
	function getComponent( $id )
	{
		if ( !isset( $this->ekObject->targetDlgVars[$id] ) ) {
			trigger_error( $id . ' is not defined in dlg_vars table. Aborting... ', E_USER_ERROR );
		}
		
		$component = $this->ekObject->targetDlgVars[$id];
		$type = strtolower( $component['ctrl_type'] );
		
		$className = 'EK_EComponent';
		
		if ( class_exists( $type ) ) {
			$className = $type;
		} else {
			if ( class_exists( 'EK_' . $type ) ) {
				$className = 'EK_' . $type;
			}
		}
		
		$comp = new $className( $this->ekObject ) ;
		return $comp->createComponent( $component );
	}
}
?>