You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

365 lines
10 KiB
PHP

<?php
/**
* SmartTemplateParser Class
* Used by SmartTemplate Class
*
* @desc Used by SmartTemplate Class
* @author Philipp v. Criegern philipp@criegern.com
* @author Manuel 'EndelWar' Dalla Lana endelwar@aregar.it
* @version 1.2.1 03.07.2006
*
* CVS ID: $Id: class.smarttemplateparser.php 2504 2011-12-28 07:35:29Z liu21st $
*/
class SmartTemplateParser
{
/**
* The template itself
*
* @access private
*/
var $template;
/**
* The template filename used to extract the dirname for subtemplates
*
* @access private
*/
var $template_dir;
/**
* List of used SmartTemplate Extensions
*
* @access private
*/
var $extension_tagged = array();
/**
* Error messages
*
* @access public
*/
var $error;
/**
* SmartTemplateParser Constructor
*
* @param string $template_filename HTML Template Filename
*/
function SmartTemplateParser ( $template_filename )
{
// Load Template
if ($hd = @fopen($template_filename, "r"))
{
if (filesize($template_filename))
{
$this->template = fread($hd, filesize($template_filename));
}
else
{
$this->template = "SmartTemplate Parser Error: File size is zero byte: '$template_filename'";
}
fclose($hd);
// Extract the name of the template directory
$this->template_dir = dirname($template_filename);
}
else
{
$this->template = "SmartTemplate Parser Error: File not found: '$template_filename'";
}
}
/**
* Main Template Parser
*
* @param string $compiled_template_filename Compiled Template Filename
* @desc Creates Compiled PHP Template
*/
function compile( $compiled_template_filename = '' )
{
if (empty($this->template))
{
return;
}
/* Quick hack to allow subtemplates */
if(eregi("<!-- INCLUDE", $this->template))
{
while ($this->count_subtemplates() > 0)
{
preg_match_all('/<!-- INCLUDE ([a-zA-Z0-9_.]+) -->/', $this->template, $tvar);
foreach($tvar[1] as $subfile)
{
if(file_exists($this->template_dir . "/$subfile"))
{
$subst = implode('',file($this->template_dir . "/$subfile"));
}
else
{
$subst = 'SmartTemplate Parser Error: Subtemplate not found: \''.$subfile.'\'';
}
$this->template = str_replace("<!-- INCLUDE $subfile -->", $subst, $this->template);
}
}
}
// END, ELSE Blocks
$page = preg_replace("/<!-- ENDIF.+?-->/", "<?php\n}\n?>", $this->template);
$page = preg_replace("/<!-- END[ a-zA-Z0-9_.]* -->/", "<?php\n}\n\$_obj=\$_stack[--\$_stack_cnt];}\n?>", $page);
$page = str_replace("<!-- ELSE -->", "<?php\n} else {\n?>", $page);
// 'BEGIN - END' Blocks
if (preg_match_all('/<!-- BEGIN ([a-zA-Z0-9_.]+) -->/', $page, $var))
{
foreach ($var[1] as $tag)
{
list($parent, $block) = $this->var_name($tag);
$code = "<?php\n"
. "if (!empty(\$$parent"."['$block'])){\n"
. "if (!is_array(\$$parent"."['$block']))\n"
. "\$$parent"."['$block']=array(array('$block'=>\$$parent"."['$block']));\n"
. "\$_tmp_arr_keys=array_keys(\$$parent"."['$block']);\n"
. "if (\$_tmp_arr_keys[0]!='0')\n"
. "\$$parent"."['$block']=array(0=>\$$parent"."['$block']);\n"
. "\$_stack[\$_stack_cnt++]=\$_obj;\n"
. "foreach (\$$parent"."['$block'] as \$rowcnt=>\$$block) {\n"
. "\$$block"."['ROWCNT']=\$rowcnt;\n"
. "\$$block"."['ALTROW']=\$rowcnt%2;\n"
. "\$$block"."['ROWBIT']=\$rowcnt%2;\n"
. "\$_obj=&\$$block;\n?>";
$page = str_replace("<!-- BEGIN $tag -->", $code, $page);
}
}
// 'IF nnn=mmm' Blocks
if (preg_match_all('/<!-- (ELSE)?IF ([a-zA-Z0-9_.]+)[ ]*([!=<>]+)[ ]*(["]?[^"]*["]?) -->/', $page, $var))
{
foreach ($var[2] as $cnt => $tag)
{
list($parent, $block) = $this->var_name($tag);
$cmp = $var[3][$cnt];
$val = $var[4][$cnt];
$else = ($var[1][$cnt] == 'ELSE') ? '} else' : '';
if ($cmp == '=')
{
$cmp = '==';
}
if (preg_match('/"([^"]*)"/',$val,$matches))
{
$code = "<?php\n$else"."if (\$$parent"."['$block'] $cmp \"".$matches[1]."\"){\n?>";
}
elseif (preg_match('/([^"]*)/',$val,$matches))
{
list($parent_right, $block_right) = $this->var_name($matches[1]);
$code = "<?php\n$else"."if (\$$parent"."['$block'] $cmp \$$parent_right"."['$block_right']){\n?>";
}
$page = str_replace($var[0][$cnt], $code, $page);
}
}
// 'IF nnn' Blocks
if (preg_match_all('/<!-- (ELSE)?IF ([a-zA-Z0-9_.]+) -->/', $page, $var))
{
foreach ($var[2] as $cnt => $tag)
{
$else = ($var[1][$cnt] == 'ELSE') ? '} else' : '';
list($parent, $block) = $this->var_name($tag);
$code = "<?php\n$else"."if (!empty(\$$parent"."['$block'])){\n?>";
$page = str_replace($var[0][$cnt], $code, $page);
}
}
// Replace Scalars
if (preg_match_all('/{([a-zA-Z0-9_. >]+)}/', $page, $var))
{
foreach ($var[1] as $fulltag)
{
// Determin Command (echo / $obj[n]=)
list($cmd, $tag) = $this->cmd_name($fulltag);
list($block, $skalar) = $this->var_name($tag);
$code = "<?php\n$cmd \$$block"."['$skalar'];\n?>\n";
$page = str_replace('{'.$fulltag.'}', $code, $page);
}
}
// ROSI Special: Replace Translations
if (preg_match_all('/<"([a-zA-Z0-9_.]+)">/', $page, $var))
{
foreach ($var[1] as $tag)
{
list($block, $skalar) = $this->var_name($tag);
$code = "<?php\necho gettext('$skalar');\n?>\n";
$page = str_replace('<"'.$tag.'">', $code, $page);
}
}
// Include Extensions
$header = '';
if (preg_match_all('/{([a-zA-Z0-9_]+):([^}]*)}/', $page, $var))
{
foreach ($var[2] as $cnt => $tag)
{
// Determin Command (echo / $obj[n]=)
list($cmd, $tag) = $this->cmd_name($tag);
$extension = $var[1][$cnt];
if (!isset($this->extension_tagged[$extension]))
{
$header .= "include_once \"smarttemplate_extensions/smarttemplate_extension_$extension.php\";\n";
$this->extension_tagged[$extension] = true;
}
if (!strlen($tag))
{
$code = "<?php\n$cmd smarttemplate_extension_$extension();\n?>\n";
}
elseif (substr($tag, 0, 1) == '"')
{
$code = "<?php\n$cmd smarttemplate_extension_$extension($tag);\n?>\n";
}
elseif (strpos($tag, ','))
{
list($tag, $addparam) = explode(',', $tag, 2);
list($block, $skalar) = $this->var_name($tag);
if (preg_match('/^([a-zA-Z_]+)/', $addparam, $match))
{
$nexttag = $match[1];
list($nextblock, $nextskalar) = $this->var_name($nexttag);
$addparam = substr($addparam, strlen($nexttag));
$code = "<?php\n$cmd smarttemplate_extension_$extension(\$$block"."['$skalar'],\$$nextblock"."['$nextskalar']"."$addparam);\n?>\n";
}
else
{
$code = "<?php\n$cmd smarttemplate_extension_$extension(\$$block"."['$skalar'],$addparam);\n?>\n";
}
}
else
{
list($block, $skalar) = $this->var_name($tag);
$code = "<?php\n$cmd smarttemplate_extension_$extension(\$$block"."['$skalar']);\n?>\n";
}
$page = str_replace($var[0][$cnt], $code, $page);
}
}
// Add Include Header
if (isset($header) && !empty($header))
{
$page = "<?php\n$header\n?>$page";
}
// Store Code to Temp Dir
if (strlen($compiled_template_filename))
{
if ($hd = fopen($compiled_template_filename, "w"))
{
fwrite($hd, $page);
fclose($hd);
return true;
}
else
{
$this->error = "Could not write compiled file.";
return false;
}
}
else
{
return $page;
}
}
/**
* Splits Template-Style Variable Names into an Array-Name/Key-Name Components
* {example} : array( "_obj", "example" ) -> $_obj['example']
* {example.value} : array( "_obj['example']", "value" ) -> $_obj['example']['value']
* {example.0.value} : array( "_obj['example'][0]", "value" ) -> $_obj['example'][0]['value']
* {top.example} : array( "_stack[0]", "example" ) -> $_stack[0]['example']
* {parent.example} : array( "_stack[$_stack_cnt-1]", "example" ) -> $_stack[$_stack_cnt-1]['example']
* {parent.parent.example} : array( "_stack[$_stack_cnt-2]", "example" ) -> $_stack[$_stack_cnt-2]['example']
*
* @param string $tag Variale Name used in Template
* @return array Array Name, Key Name
* @access private
* @desc Splits Template-Style Variable Names into an Array-Name/Key-Name Components
*/
function var_name($tag)
{
$parent_level = 0;
while (substr($tag, 0, 7) == 'parent.')
{
$tag = substr($tag, 7);
$parent_level++;
}
if (substr($tag, 0, 4) == 'top.')
{
$obj = '_stack[0]';
$tag = substr($tag,4);
}
elseif ($parent_level)
{
$obj = '_stack[$_stack_cnt-'.$parent_level.']';
}
else
{
$obj = '_obj';
}
while (is_int(strpos($tag, '.')))
{
list($parent, $tag) = explode('.', $tag, 2);
if (is_numeric($parent))
{
$obj .= "[" . $parent . "]";
}
else
{
$obj .= "['" . $parent . "']";
}
}
$ret = array($obj, $tag);
return $ret;
}
/**
* Determine Template Command from Variable Name
* {variable} : array( "echo", "variable" ) -> echo $_obj['variable']
* {variable > new_name} : array( "_obj['new_name']=", "variable" ) -> $_obj['new_name']= $_obj['variable']
*
* @param string $tag Variale Name used in Template
* @return array Array Command, Variable
* @access private
* @desc Determine Template Command from Variable Name
*/
function cmd_name($tag)
{
if (preg_match('/^(.+) > ([a-zA-Z0-9_.]+)$/', $tag, $tagvar))
{
$tag = $tagvar[1];
list($newblock, $newskalar) = $this->var_name($tagvar[2]);
$cmd = "\$$newblock"."['$newskalar']=";
}
else
{
$cmd = "echo";
}
$ret = array($cmd, $tag);
return $ret;
}
/**
* @return int Number of subtemplate included
* @access private
* @desc Count number of subtemplates included in current template
*/
function count_subtemplates()
{
preg_match_all('/<!-- INCLUDE ([a-zA-Z0-9_.]+) -->/', $this->template, $tvar);
$count_subtemplates = count($tvar[1]);
$ret = intval($count_subtemplates);
return $ret;
}
}
?>