<?php
/**
* SmartTemplateDebugger Class
* Used by SmartTemplate Class
*
* @author Philipp v. Criegern [email protected]
* @version 1.01 08.05.2002
* @desc Used by SmartTemplate Class
*/
class SmartTemplateDebugger
{
var $vars;
var $functions;
var $code; /**
* The template Filename
*
* @access private
*/
var $filename; /**
* The template itself
*
* @access private
*/
var $template; /**
* SmartTemplateParser Constructor
*
* @param string $template_filename HTML Template Filename
*/
function SmartTemplateDebugger ( $template_filename )
{
$this->filename  =  $template_filename;
// Load Template
if ($hd  =  @fopen($template_filename,  "r"))
{
$this->template  =  fread($hd,  filesize($template_filename));
fclose($hd);
}
else
{
$this->template  =  "File not found: '$template_filename'";
}
$this->tab[0]  =  '';
for ($i=1;  $i < 10;  $i++) {
$this->tab[$i]  =  str_repeat('    ', $i);
}
}
/**
* Main Template Parser
*
* @param string $compiled_template_filename Compiled Template Filename
* @desc Creates Compiled PHP Template
*/
function start ( $vars="" )
{
$page  =  $this->template; $page  =  preg_replace("/(<!-- BEGIN [ a-zA-Z0-9_.]* -->)/",  "\n$1\n",  $page);
$page  =  preg_replace("/(<!-- IF .+? -->)/",  "\n$1\n",  $page);
$page  =  preg_replace("/(<!-- END.*? -->)/",  "\n$1\n",  $page);
$page  =  preg_replace("/(<!-- ELSEIF .+? -->)/",  "\n$1\n",  $page);
$page  =  preg_replace("/(<!-- ELSE [ a-zA-Z0-9_.]*-->)/",  "\n$1\n",  $page); $page  =  $this->highlight_html($page); $rows      =  explode("\n",  $page);
$page_arr  =  array();
$level     =  0;
$blocklvl  =  0;
$rowcnt    =  0;
$spancnt   =  0;
$offset    =  22;
$lvl_block =  array();
$lvl_row   =  array();
$lvl_typ   =  array();
foreach ($rows as $row)
{
if ($row  =  trim($row))
{
$closespan  =  false;
if (substr($row, $offset, 12) == '&lt;!-- END ')
{
if ($level < 1)
{
$level++;
$error[$rowcnt]  =  "END Without BEGIN";
}
elseif ($lvl_typ[$level] != 'BEGIN')
{
$error[$lvl_row[$level]]  =  "IF without ENDIF";
$error[$rowcnt]  =  "END Without BEGIN";
}
$blocklvl--;
$level--;
$closespan  =  true;
}
if (substr($row, $offset, 14) == '&lt;!-- ENDIF ')
{
if ($level < 1)
{
$level++;
$error[$rowcnt]  =  "ENDIF Without IF";
}
elseif ($lvl_typ[$level] != 'IF')
{
$error[$lvl_row[$level]]  =  "BEGIN without END";
$error[$rowcnt]  =  "ENDIF Without IF";
}
$closespan  =  true;
$level--;
}
if ($closespan)
{
$page_arr[$rowcnt-1]  .=  '</span>';
}
$this_row  =  $this->tab[$level] . $row;
if (substr($row, $offset, 12) == '&lt;!-- ELSE')
{
if ($level < 1)
{
$error[$rowcnt]  =  "ELSE Without IF";
}
elseif ($lvl_typ[$level] != 'IF')
{
$error[$rowcnt]  =  "ELSE Without IF";
}
else
{
$this_row  =  $this->tab[$level-1] . $row;
}
}
if (substr($row, $offset, 14) == '&lt;!-- BEGIN ')
{
if ($blocklvl == 0)
{
if ($lp = strpos($row, '--&gt;'))
{
if ($blockname  =  trim(substr($row, $offset + 14, $lp -$offset -14)))
{
if ($nr = count($vars[$blockname]))
{
$this_row  .=  $this->toggleview("$nr Entries");
}
else
{
$this_row  .=  $this->toggleview("Emtpy");
}
}
}
}
else
{
$this_row  .=  $this->toggleview('[');
}
$blocklvl++;
$level++;
$lvl_row[$level]  =  $rowcnt;
$lvl_typ[$level]  =  'BEGIN';
}
elseif (substr($row, $offset, 11) == '&lt;!-- IF ')
{
$level++;
$lvl_row[$level]  =  $rowcnt;
$lvl_typ[$level]  =  'IF';
$this_row  .=  $this->toggleview();
}
$page_arr[]  =  $this_row;
$lvl_block[$rowcnt]  =  $blocklvl;
$rowcnt++;
}
}
if ($level > 0)
{
$error[$lvl_row[$level]]  =  "Block not closed";
} $page  =  join("\n", $page_arr);
$rows  =  explode("\n",  $page);
$cnt   =  count($rows); for ($i = 0;  $i < $cnt;  $i++)
{
// Add Errortext
if ($err = $error[$i])
{
$rows[$i]  =  '<b>' . $rows[$i] . '        ERROR: ' . $err . '!</b>';
} // Replace Scalars
if (preg_match_all('/{([a-zA-Z0-9_. &;]+)}/', $rows[$i], $var))
{
foreach ($var[1] as $tag)
{
$fulltag  =  $tag;
if ($delim = strpos($tag, ' &gt; '))
{
$tag  =  substr($tag, 0, $delim);
}
if (substr($tag, 0, 4) == 'top.')
{
$title  =  $this->tip($vars[substr($tag, 4)]);
}
elseif ($lvl_block[$i] == 0)
{
$title  =  $this->tip($vars[$tag]);
}
else
{
$title  =  '[BLOCK?]';
}
$code  =  '<b title="' . $title . '">{' . $fulltag . '}</b>';
$rows[$i]  =  str_replace('{'.$fulltag.'}',  $code,  $rows[$i]);
}
} // Replace Extensions
if (preg_match_all('/{([a-zA-Z0-9_]+):([^}]*)}/', $rows[$i], $var))
{
foreach ($var[2] as $tmpcnt => $tag)
{
$fulltag  =  $tag;
if ($delim = strpos($tag, ' &gt; '))
{
$tag  =  substr($tag, 0, $delim);
}
if (strpos($tag, ','))
{
list($tag, $addparam)  =  explode(',', $tag, 2);
}
$extension  =  $var[1][$tmpcnt]; if (substr($tag, 0, 4) == 'top.')
{
$title  =  $this->tip($vars[substr($tag, 4)]);
}
elseif ($lvl_block[$i] == 0)
{
$title  =  $this->tip($vars[$tag]);
}
else
{
$title  =  '[BLOCK?]';
}
$code  =  '<b title="' . $title . '">{' . $extension . ':' . $fulltag . '}</b>';
$rows[$i]  =  str_replace('{'.$extension . ':' . $fulltag .'}',  $code,  $rows[$i]);
}
}

解决方案 »

  1.   

    // 'IF nnn' Blocks
    if (preg_match_all('/&lt;!-- IF ([a-zA-Z0-9_.]+) --&gt;/', $rows[$i], $var))
    {
    foreach ($var[1] as $tag)
    {
    if (substr($tag, 0, 4) == 'top.')
    {
    $title  =  $this->tip($vars[substr($tag, 4)]);
    }
    elseif ($lvl_block[$i] == 0)
    {
    $title  =  $this->tip($vars[$tag]);
    }
    else
    {
    $title  =  '[BLOCK?]';
    }
    $code  =  '<span title="' . $title . '">&lt;!-- IF ' . $tag . ' --&gt;</span>';
    $rows[$i]  =  str_replace("&lt;!-- IF $tag --&gt;",  $code,  $rows[$i]);
    if ($title == '[NULL]')
    {
    $rows[$i]  =  str_replace('Hide',  'Show',  $rows[$i]);
    $rows[$i]  =  str_replace('block',  'none',  $rows[$i]);
    }
    }
    }
    }
    $page  =  join("<br>", $rows); // Print Header
    echo '<html><head><script type="text/javascript">
    function toggleVisibility(el, src) {
    var v = el.style.display == "block";
    var str = src.innerHTML;
    el.style.display = v ? "none" : "block";
    src.innerHTML = v ? str.replace(/Hide/, "Show") : str.replace(/Show/, "Hide");}
    </script></head><body>'; // Print Index
    echo '<font face="Arial" Size="3"><b>';
    echo 'SmartTemplate Debugger<br>';
    echo '<font size="2"><li>PHP-Script: ' . $_SERVER['PATH_TRANSLATED'] . '</li><li>Template: ' . $this->filename . '</li></font><hr>';
    echo '<li><a href="#template_code">Template</a></li>';
    echo '<li><a href="#compiled_code">Compiled Template</a></li>';
    echo '<li><a href="#data_code">Data</a></li>';
    echo '</b></font><hr>'; // Print Template
    echo '<a name="template_code"><br><font face="Arial" Size="3"><b>Template:</b>&nbsp;[<a href="javascript:void(\'\');" onclick="toggleVisibility(document.getElementById(\'Template\'), this); return false">Hide Ouptut</a>]</font><br>';
    echo '<table border="0" cellpadding="4" cellspacing="1" width="100%" bgcolor="#C6D3EF"><tr><td bgcolor="#F0F0F0"><pre id="Template" style="display:block">';
    echo $page;
    echo '</pre></td></tr></table>'; // Print Compiled Template
    include_once ("class.smarttemplateparser.php");
    $parser = new SmartTemplateParser($this->filename);
    $compiled  =  $parser->compile();
    echo '<a name="compiled_code"><br><br><font face="Arial" Size="3"><b>Compiled Template:</b>&nbsp;[<a href="javascript:void(\'\');" onclick="toggleVisibility(document.getElementById(\'Compiled\'), this); return false">Hide Ouptut</a>]</font><br>';
    echo '<table border="0" cellpadding="4" cellspacing="1" width="100%" bgcolor="#C6D3EF"><tr><td bgcolor="#F0F0F0"><pre id="Compiled" style="display:block">';
    highlight_string($compiled);
    echo '</pre></td></tr></table>'; // Print Data
    echo '<a name="data_code"><br><br><font face="Arial" Size="3"><b>Data:</b>&nbsp;[<a href="javascript:void(\'\');" onclick="toggleVisibility(document.getElementById(\'Data\'), this); return false">Hide Ouptut</a>]</font><br>';
    echo '<table border="0" cellpadding="4" cellspacing="1" width="100%" bgcolor="#C6D3EF"><tr><td bgcolor="#F0F0F0"><pre id="Data" style="display:block">';
    $vars = $this->get_vars();
    echo $this->vardump($vars);
    echo '</pre></td></tr></table></body></html>';
    } /**
    * Insert Hide/Show Layer Switch
    *
    * @param string $suffix Additional Text
    * @desc Insert Hide/Show Layer Switch
    */
    function toggleview ( $suffix = '')
    {
    global $spancnt; $spancnt++;
    if ($suffix)
    {
    $suffix  .=  ':';
    }
    return '[' . $suffix . '<a href="javascript:void(\'\');" onclick="toggleVisibility(document.getElementById(\'Block' . $spancnt . '\'), this); return false">Hide Block</a>]<span id="Block' . $spancnt . '" style="display:block">';
    } /**
    * Create Title Text
    *
    * @param string $value Content
    * @desc Create Title Text
    */
    function tip ( $value )
    {
    if (empty($value))
    {
    return "[NULL]";
    }
    else
    {
    return htmlentities(substr($value,0,200));
    }
    } /**
    * Recursive Variable Display Output
    *
    * @param mixed $var Content
    * @param int $depth Incremented Indent Counter for Recursive Calls
    * @return string Variable Content
    * @access private
    * @desc Recursive Variable Display Output
    */
    function vardump($var, $depth = 0)
    {
    if (is_array($var))
    {
    $result  =  "Array (" . count($var) . ")<BR>";
    foreach(array_keys($var) as $key)
    {
    $result  .=  $this->tab[$depth] . "<B>$key</B>: " . $this->vardump($var[$key],  $depth+1);
    }
    return $result;
    }
    else
    {
    return htmlspecialchars($var) . "<BR>";
    }
    } /**
    * Splits Template-Style Variable Names into an Array-Name/Key-Name Components
    *
    * @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.')
    {
    return array('_stack[0]', substr($tag,4));
    }
    elseif ($parent_level)
    {
    return array('_stack[$_stack_cnt-'.$parent_level.']', $tag);
    }
    else
    {
    return array('_obj', $tag);
    }
    }
      

  2.   

    /**
    * Highlight HTML Source
    *
    * @param string $code HTML Source
    * @return string Hightlighte HTML Source
    * @access private
    * @desc Highlight HTML Source
    */
    function highlight_html ( $code )
    {
    $code  =  htmlspecialchars($code);
    $code  =  preg_replace('/([a-zA-Z_]+)=/',  '<font color="#FF0000">$1=</font>',  $code);
    $code  =  preg_replace('/(&lt;[\/a-zA-Z0-9&;]+)/',  '<font color="#0000FF">$1</font>',  $code);
    $code  =  str_replace('&lt;!--',  '<font color="#008080">&lt;!--',  $code);
    $code  =  str_replace('--&gt;',  '--&gt;</font>',  $code);
    $code  =  preg_replace('/[\r\n]+/',  "\n",  $code);
    return $code;
    } function get_vars() {
    $str = $this->template;
    preg_match_all("/<!--.*-->|{\w.*}/U",$str,$regs); $stack = array();
    $vars = array();
    $functions = array();
    $key = 0; // = chr(ord("i")+count($stack));
    $LF = "\r\n";
    $outstr = "";
    foreach($regs[0] as $v) {
    if(preg_match_all("/<!-- BEGIN (\w+) -->/",$v, $r)) {
    array_push($stack,$r[1][0]);
    $k = chr(ord("i")+$key++);
    $outstr .= str_repeat(chr(9), $key-1)."/* 对数组 \${$r[1][0]} 赋值 */$LF";
    $outstr .= str_repeat(chr(9), $key-1)."for(\$$k=0;\$$k<1;\$$k++) \{$LF";
    }elseif(preg_match_all("/<!-- END (\w+) -->/",$v, $r)) {
    $v = array_pop($stack);
    $outstr .= str_repeat(chr(9), --$key)."}$LF";
    if($key) {
    $k = chr(ord("i")+$key-1);
    $p = $stack[$key-1];
    $outstr .= str_repeat(chr(9), $key)."\${$p}[\$$k][$v] = \$$v;$LF";
    }else
    $outstr .= "\$data[$v] = \$$v;$LF";
    }elseif(preg_match_all("/{(\w+)}/",$v, $r)) {
    if(count($stack)) {
    $v = $stack[$key-1];
    $k = chr(ord("i")+$key-1);
    $outstr .= str_repeat(chr(9), count($stack))."\${$v}[\$$k][{$r[1][0]}] = '{$r[1][0]}测试';$LF";
    $ch = "\$data[".join("][][",$stack)."][{$r[1][0]}]";
    if(! in_array($ch, $vars))
    $vars[] = $ch;
    }else
    if(! in_array("\$data[{$r[1][0]}]", $vars)) {
    $vars[] = "\$data[{$r[1][0]}]";
    $outstr .= "\$data[{$r[1][0]}] = '{$r[1][0]}测试';$LF";
    }
    }elseif(preg_match_all("/{(\w+):([^}]+)/",$v, $r)) {
    $ch = $r[1][0]."({$r[2][0]})";
    $define = true;
    if (! function_exists("smarttemplate_extension_{$r[1][0]}")) {
    if(! include("smarttemplate_extensions/smarttemplate_extension_{$r[1][0]}.php"))
    $define = false;
    }
    $functions[] = array(name=>$ch, define=>$define);
    foreach(split(",",$r[2][0]) as $v)
    if($v[0] != '"')
    if(! in_array($v, $vars)) {
    $vars[] = "\$data[$v]";
    $outstr .= "\$data[$v] = '$v测试';$LF";
    }
    }elseif(preg_match_all("/<!-- IF (\w+)/",$v, $r)) {
    if(! in_array("\$data[{$r[1][0]}]", $vars)) {
    $vars[] = "\$data[{$r[1][0]}]";
    $outstr .= "\$data[{$r[1][0]}] = '{$r[1][0]}测试';$LF";
    }
    }
    }
    $this->vars = $vars;
    $this->functions =$functions;
    $this->code = $outstr;
    eval("$outstr;");
    return $data;
    } function gen($file_name="") {
    ob_start(); $LF = "\r\n";
    echo "<?php$LF";
    echo "/**$LF";
    echo " * 模板 $this->filename$LF";
    echo " * 使用了如下变量,请对其赋值$LF";
    foreach($this->vars as $v)
    echo " * $v$LF"; echo " *$LF";
    echo " * 使用了如下模板函数$LF";
    $ar = array();
    foreach($this->functions as $k=>$v) {
    echo " * $v[name]$LF";
    if(! $v[define]) $ar[] = $k;
    }
    if(count($ar)) {
    $path = "smarttemplate_extensions";
    if(! is_dir($path)) {
    mkdir($path,0666);
    chmod($path,0666);
    }
    echo " *$LF";
    echo " * 其中以下函数未定义,请定义$LF";
    foreach($ar as $k) {
    $v = $this->functions[$k][name];
    $name = preg_replace("/(\w+).*/","\\1",$v);
    echo " * $v => $path/{$path}_$name.php$LF";
     
    $fp = fopen("$path/{$path}_$name.php","w");
    fwrite($fp,"<?php$LF");
    fwrite($fp,"function {$path}_$v \{$LF");
    fwrite($fp,"  return '函数$v';$LF");
    fwrite($fp,"}$LF?>$LF");
    fclose($fp);
    }
    } echo " **/$LF";
    echo "$LF";
    echo "/** 对模板变量赋值的可能形式 **/$LF"; echo $this->code; echo "$LF";
    echo "/** 加载并执行模板 **/$LF";
    echo "require_once 'class.smarttemplate.php';$LF";
    echo "\$page = new SmartTemplate('$this->filename');$LF";
    echo "\$page->assign(\$data);$LF";
    echo "\$page->output();$LF";
    echo "?>$LF"; $code  =  ob_get_contents(); 
    ob_end_clean(); if($file_name == "") {
    $fname = basename($this->filename);
    $fname = substr($fname,0,strrpos($fname,".")+1)."php";
    }else
    $fname = $file_name; $fp = fopen($fname,"w");
    fwrite($fp,$code);
    fclose($fp); }
    }?>
      

  3.   

    请问与PHPLIB相比较有哪些优势?
    我一直在用PHPLIB,在显示变量上可以处理的很好,
    但是如果进行分页处理时,用块解析就不行了,不知道有什么好办法
      

  4.   

    奇怪了,散分都没人要吗?
    与PHPLIB的template相比,smarttemplate 至少有以下优势:
    1、编译型模板,运行速度快
    2、可扩展模板函数,较好的解决了模板的个性化问题除去模板中的流程控制标记,两者在模板的书写和可视化程度上一样
      

  5.   

    强烈支持,现在对于速度要求较高的项目都使用的是smart.
    在smart的论坛里有不少好的hack可用。比如多个模板嵌套。
      

  6.   

    听老大说 SMARTYTEMPLATE 这么棒  我也想用用了 ,我一直用SMARTY
      

  7.   

    smarttemplate的网址:http://www.smartphp.net它小巧简单容易使用,smrty、phplib那些没法比。
      

  8.   

    他有个BUG就是
    和CSS的样式有点冲突,所以做的时候要注意
    <!--
    .my {font-size: 10px}
    -->
    如这样他就会报错。。
      

  9.   

    天哪天哪 我的天哪 我可找到你了
    我很喜欢smarttemplate!
      

  10.   

    唠叨你下面贴的是什么呀 Highlight HTML Source这些也是它里面的吗
      

  11.   

    借这个地方问个问题:
    我以前用Smarty
    比如我有一个这样的变量:$name = "Name Test";
    想显示为:“NAME_TEST"
    在Smartty中可以这样:{$name|upper|replace:" ":"_"}
    但在SmartTemplate中如何操作呢?虽然它里面也有相关的函数,但我不知道如何组合起来。
      

  12.   

    to nullfox(我把青春毁给你)
     是的to felio(cvcstudio.com) 
     目前各种模板都存在这个问题,除非模板变量不用{}括起
     另外请注意到示例文件中样式表的写法:
    <style>
    .my { font-size: 10px }
    </style>
    这样就不会被解释成模板变量或函数了
    而且看上去也很美观
      

  13.   

    to (唠叨) :
    感觉smarttemplate的include不太方便呢
    你觉得呢还有我见过一个template可以自定义模版标签符的,不知道smarttpl能不能改造一下哦
      

  14.   

    to nullfox(我把青春毁给你) 
    你是指当include进来的php程序也使用了smarttemplate模板这个情况吗?
    class.smarttemplate.php有个小bug,你只需把
    unset ($_top);
    改为
    unset ($GLOBALS[_top]);
    就可以了你也可以扩展smarttemplate方法,让他支持多模板文件
      

  15.   

    我使用phplib,不过值得关注,我已经看过smarty,可是一值没有在实际
    项目中使用
      

  16.   

    to (唠叨):
    我指的是模版之间的套嵌,比如index.html包含一个foot.html,这样子
      

  17.   

    to nullfox(我把青春毁给你) 
    模板文件不宜做嵌套,那样会破坏可视化程度。
      

  18.   

    to 唠叨:
    套嵌就是为了方便亚
    所有的页面都共用一个顶部样式,为什么不include一个top.html而在每个模版文件内重复一段完全相同的代码呢。修改起来很不方便哦
    一些模版体系通常使用:{include:top.html}来做套嵌
    而smarttemplate却没这样的简便语法
      

  19.   

    目前各种模板都存在这个问题,除非模板变量不用{}括起
     smarty可以自定义标签的,我们是自定义为<smarty>和</smarty>很有效
      

  20.   

    en,我一直在用smarty,如果楼主说smarttemplate好的话,我也关注一下
      

  21.   

    散分没人要么?我要-_________-!!!
    现在对模板失去兴趣了,郁闷,现在都直接用PHP了