喜悦国际村 
» 游客:  注册 | 登录 | 搜索 | 统计 | 喜悦证交所 | 帮助

RSS 订阅当前论坛  

【村长请吃饭啊】 ---北京诚聘--- 【你还在犹豫吗?】

上一主题 下一主题
     
标题: [原创] 新写了一个模板类,提些意见~  
 
idgnarn
新手上路
Rank: 1


UID 88636
精华 0
积分 31
帖子 28
金钱 31 喜悦币
威望 0
人脉 0
阅读权限 10
注册 2007-2-28
状态 离线
新写了一个模板类,提些意见~



<?
define
('_IN_NSTEMPLATE'1);

class 
templateconf{
    public 
$conf = array(
        
'root' => './',
        
'lang' => 'chs',
        
'compiledfolder' => 'compiled',
        
'unknowns' => 'comment',
        
'cachetimeout' => 20000,
        
'enablecahce' => false,
        
'erron' => true,
        
'debugon' => false,
    );
    public 
$_block_regcounterstr 255;
    public 
$_last_selectedblock 0;
    public 
$_reg_blocks = array();
    public 
$_blockmap = array();
    public 
$_blockstrmap = array();
}
class 
template extends templateconf{
    
    function 
__construct($tplpath$conf = array()){
        
        
//配置
        
if(!empty($conf)){
            foreach(
$conf as $varname => $value){
                
$this->conf[$varname] = $value;
            }
        }
        
        
//原始文件路径
        
$this->tplpath $tplpath;
        
//临时文件路径
        
$this->temporarypath $this->conf['root'].$this->conf['compiledfolder'].'/temporary-'.$this->conf['lang'].'-'.md5(basename($this->tplpath)).'.tmp.php';
        
//编译文件路径
        
$this->compiledpath $this->conf['root'].$this->conf['compiledfolder'].'/compiled-'.$this->conf['lang'].'-'.md5(basename($this->tplpath)).'.cp.php';
        
//编译数据文件路径
        
$this->compileddatpath $this->conf['root'].$this->conf['compiledfolder'].'/compiled-dat-'.$this->conf['lang'].'-'.md5(basename($this->tplpath)).'.data.php';

        if(!
is_readable($this->tplpath)){
            
$this->_halt('模板载入错误,文件不存在或无法读取'"{$this->tplpath}");
        }
        
        if(!
file_exists($this->conf['root'].$this->conf['compiledfolder'])){
            
$this->_halt('临时文件夹不存在',"\"{$this->conf['root']}{$this->conf['compiledfolder']}\"  不存在");
        }
        
        if(!
is_readable($this->compiledpath)){
            
//编译模板
            
$this->cachedfile false;
            
$this->_preprocess();
         }elseif((
intval(time() - @filemtime($this->compiledpath)) > $this->conf['cachetimeout']) || !$this->conf['enablecahce']){
            
//编译模板
            
$this->cachedfile false;
            
$this->_preprocess();
        }else{
            require(
$this->compileddatpath);
        }
    }
    
    
//处理静态变量,模块
    
function _preprocess(){
        
//读原始模板
        
$this->source implode('', @file($this->tplpath));
        
$this->_safe_check();
        
$this->_process();
        if(
$this->conf['enablecahce'] && !$this->cachedfile){
            
$this->writetofile($this->compiledpath$this->datafileheader().$this->source);
        }
    }
    
    function 
_process(){
        
//取词
        
do{
            
$this->_tokenstatement();
            
$this->handletoken($this->_token$this->source);
        }while(!empty(
$this->_token));
        
//处理转义
        
$this->_process_trans();
        
$this->_storecompiled();
        
    }
    
    function 
block($blockname){
        
//获取BLOCK编号
        
if(isset($this->_blockmap[$blockname])){
            
$this->selectedblock $this->_blockmap[$blockname]; 
        }else{
            
$this->_halt('定义不存在的结构'"'{$blockname}'");
        }
        if(!isset(
$this->_temp_counter[$this->selectedblock])) $this->_temp_counter[$this->selectedblock] = 0;
        
//查找子BLOCK
        
$childthis->selectedblock array_search($this->selectedblock$this->_blockparent); 
        
        if(!empty(
$childthis->selectedblock) && ($this->_last_selectedblock !=$this->selectedblock)){
            
$this->_temp_counter[$childthis->selectedblock] = 0;
        }
        
//当前BLOCK计数器
        
$this->_temp_counter[$this->selectedblock]++;
        
$this->_last_selectedblock $this->selectedblock;
/*        if($this->_block_reg != 0){
            $this->_halt('重复定义BLOCK');
        }*/

        
$_temp_strmap_compiled $this->_blockstrmap[$this->selectedblock];
        
preg_match_all('/{$_i(.+?)}/'$_temp_strmap_compiled$matches);
        foreach(
$matches[1] as $name => $value){
            
$_temp_strmap_compiled str_replace("{$_i{$value}}"$this->_temp_counter[$value], $_temp_strmap_compiled);
        }
        
$_temp_strmap_compiled preg_replace("/{(.+?)}/"'0'$_temp_strmap_compiled);
        
preg_match('/^(.*)(?:_(.+?))+$/'$_temp_strmap_compiled$matches);
        if(isset(
$matches[1])) 
            
$this->_strmap_compiled[$this->selectedblock][0] = $matches[1];
        if(isset(
$matches[2])) 
            
$this->_strmap_compiled[$this->selectedblock][1] = $matches[2];
            
$this->_strmap_compiled[$this->selectedblock][2] = $_temp_strmap_compiled;


    }
    
    function 
processblock(){
    
//    
        
if(!empty($this->_blockparent[$this->selectedblock])){
            
$this->selectedblock $this->_blockparent[$this->selectedblock];
        }
    }
    
    function 
assign($varname$value ''){
        global 
$_nstem_blockvars,$_nstem_vars;
        
        if(empty(
$this->selectedblock)){
            if (!
is_array($varname)) {
                
$_nstem_vars[$varname] = $value;
                
$this->bdo("<b>Var set:</b> $_nstem_vars['$varname']='{$value}'");
            }else{
                foreach(
$varname as $name=> $value){
                    
$_nstem_vars[$name] = $value;
                    
$this->bdo("<b>Array set:</b> $_nstem_vars['$name']='{$value}'");
                }
            }
        }else{
            if (!
is_array($varname)) {
                    if(!empty(
$this->_strmap_compiled[$this->selectedblock][0]) && !empty($this->_strmap_compiled[$this->selectedblock][1])){
                        
$_nstem_blockvars[$this->selectedblock][$this->_strmap_compiled[$this->selectedblock][0]][$this->_strmap_compiled[$this->selectedblock][1]][$varname] = $value;
                        
$_nstem_vars[$varname] = $value;
                        
$this->bdo("<b>Var set:</b> $_nstem_blockvars['$this->selectedblock'][{$this->_strmap_compiled[$this->selectedblock][0]}][{$this->_strmap_compiled[$this->selectedblock][1]}]['$varname']='{$value}'");
                    
                    }else{
                        
$_nstem_blockvars[$this->selectedblock][$this->_strmap_compiled[$this->selectedblock][2]][$varname] = $value;
                        
$_nstem_vars[$varname] = $value;
                        
$this->bdo("<b>Var set:</b> $_nstem_blockvars['$this->selectedblock'][{$this->_strmap_compiled[$this->selectedblock][2]}]['$varname']='{$value}'");
                    
                    }
            }else{
                foreach(
$varname as $name=> $value){
                    if(!empty(
$this->_strmap_compiled[$this->selectedblock][0]) && !empty($this->_strmap_compiled[$this->selectedblock][1])){
                        
$_nstem_blockvars[$this->selectedblock][$this->_strmap_compiled[$this->selectedblock][0]][$this->_strmap_compiled[$this->selectedblock][1]][$name] = $value;
                        
$_nstem_vars[$name] = $value;
                        
$this->bdo("<b>Var set:</b> $_nstem_blockvars['$this->selectedblock'][{$this->_strmap_compiled[$this->selectedblock][0]}][{$this->_strmap_compiled[$this->selectedblock][1]}]['$name']='{$value}'");
                    
                    }else{
                        
$_nstem_blockvars[$this->selectedblock][$this->_strmap_compiled[$this->selectedblock][2]][$name] = $value;
                        
$_nstem_vars[$name] = $value;
                        
$this->bdo("<b>Var set:</b> $_nstem_blockvars['$this->selectedblock'][{$this->_strmap_compiled[$this->selectedblock][2]}]['$name']='{$value}'");
                    
                    }
                }
            }
        }
    }
    
    function 
setblocks($blockname$parent ''){
        
//设置嵌套结构
        
if(isset($this->_blockmap[$parent])){
            
$this->_blockparent[$this->_blockmap[$blockname]] = $this->_blockmap[$parent];
        }else{
            
$this->_halt("定义不存在的结构""'{$parent}'");
        }
    }
    
    function 
push($pushout true){
        global 
$_nstem_blockvars,$_nstem_vars;
        
        if(
$this->conf['enablecahce']){
            if(
$pushout) require($this->compiledpath);
        }else{
            
$this->writetofile($this->temporarypath$this->datafileheader().$this->source);
            if(
$pushout) require($this->temporarypath);
        }
    }
    
    function 
_halt($message$more ''){
        
$this->lasterrmsg $message;
        if(
$this->conf['erron']){
            die(
"<h4>错误: {$message}</h4>
            {$more}"
);
        }
    }
    
    function 
datafileheader(){
        return 
"<?phpn/* NSTemplate 0.14 Build 2250 */nif(!defined('_IN_NSTEMPLATE'))die('Access Denied');nerror_reporting(E_ALL&~E_NOTICE);n?>nn";
    }
    
    function 
_storecompiled(){
        
$temp $this->datafileheader()."<?phpn";
        foreach(
$this->_blockmap as $key => $value){
            
$temp .= "$this->_blockmap['{$key}'] = '{$value}';n";
        }
        foreach(
$this->_blockstrmap as $key => $value){
            
$temp .= "$this->_blockstrmap['{$key}'] = '{$value}';n";
        }
        
$temp .= "$this->_block_reg = 0;n?>";
        
$this->writetofile($this->compileddatpath$temp);
    }
    
    function 
bdo($message){
        
$this->lasterrmsg $message;
        if(
$this->conf['debugon']){
            echo(
"<br />{$message}");
        }
    }
    
    function 
_safe_check(){
        
$this->source $this->_source preg_replace("/<s*?(.*)?s*>/is"""$this->source);
    }
    
    function 
writetofile($filename$source){
        
$fp fopen($filename'w');
        
flock($fpLOCK_EX);
        
$file_source fwrite($fp$source);
        
fclose($fp);
    }
    
    function 
_tokenstatement(){
        
//获取表达式
        
if(preg_match("/((?:<!--s*#s*|!|){(.+?)}(?:s*#s*-->|))/"$this->_source$matches)){
            
//完整表达式内容statement
            
$this->_token trim($matches[2]);
            
//完整表达式{statement} or <!--#statement#-->
            
$this->_tokenstr trim($matches[1]);
            
$this->bdo("<b>Tokenstr:</b> {$this->_tokenstr}");
            
            if(
substr($this->_tokenstr01) == '!'){
                    
//转义
                    
$this->source str_replace($this->_tokenstr"{trans:{$this->_token}}"$this->source);
                    
$this->_source str_replace($this->_tokenstr''$this->_source);
                    
$this->_token "trans:{$this->_token}";
                    
$this->_tokenstr "{trans:{$this->_token}}";
            }else{
                
$_replace_tokenstr '/'.str_replace('/''/' preg_quote($this->_tokenstr)).'/';
                
$this->_source preg_replace($_replace_tokenstr''$this->_source1);
            }
        }else{
            
$this->_token '';
            
$this->_tokenstr '';
        }
    }
        
    
//处理开始==========================================================================================
    
function handletoken($statement){
        
        
//statement(statement):statement
        
if(preg_match("/^(.+?)((.+?)):(.+?)$/",$statement$matches)){
            
$this->laststatement $matches[1];
            
            switch (
$this->laststatement) {
                case 
'set'
                    
$this->_process_set($matches[2], $matches[3]);
                    break;
            }
        
//statement:statement
        
}elseif(preg_match("/^(.+?):(.+?)$/",$statement$matches)){
            
$this->laststatement $matches[1];
            
            switch (
$this->laststatement) {
                case 
'php'
                    
$this->_set($matches[2]);
                    break;
                case 
'if'
                    
$this->_process_if($matches[2]);
                    break;
                case 
'elseif'
                    
$this->_process_if($matches[2], 'elseif');
                    break;
                case 
'lang':
                    
$this->_process_lang($matches[2]);
                    break;
                case 
'definelang':
                    
$this->_process_definelang($matches[2]);
                    break;
                case 
'static':
                    
$this->_process_static($matches[2]);
                    break;
                case 
'global'
                    
$this->_process_vars($matches[2], 'global');
                    break;
                case 
'block'
                    
$this->_process_blockbegin($matches[2]);
                    break;
            }
        
//statement
        
}else{
            
$this->laststatement $statement;
            
            switch (
$this->laststatement) {
                case 
'else'
                    
$this->_set("}else{");
                    break;
                case 
'/if'
                    
$this->_process_endtag();
                    break;
                case 
'/block'
                    
$this->_process_blockend();
                    break;
                default:
                    
$this->_process_vars($statement);
                    break;
            }
        }
    }
    
//处理结束==========================================================================================
     
    //模块处理====================================================================================================
    
function _set($statement){
        
$this->source str_replace($this->_tokenstr"<?php {$statement} ?>"$this->source);
    }
    
    function 
_process_endtag(){
        
$this->_set("}");
    }
    
    function 
_process_trans(){
        
$this->source preg_replace("/(?:<!--s*#s*|){trans:(.+?)}(?:s*#s*-->|)/is""{\1}"$this->source);
    }
    
    function 
_process_blockbegin($blockname){
        
$this->_block_reg++;
        
$this->_block_regcounterstr--;
        
$this->_blockmap[$blockname] = $this->_block_regcounterstr;
        if(
$this->_block_reg != 1){
            
$this->_block_counterstr .= "_{$_i{$this->_block_regcounterstr}}";
            
$this->block_counterstr .= ".'_'.$_i{$this->_block_regcounterstr}";
        }else{
            
$this->_block_counterstr "{$_i{$this->_block_regcounterstr}}";
            
$this->block_counterstr "$_i{$this->_block_regcounterstr}";
        }
        
$this->_blockstrmap[$this->_block_regcounterstr] = $this->_block_counterstr;
        
preg_match("/^(.*).'_'.(.*)$/"$this->block_counterstr$matches);
        if(isset(
$matches[1])) $this->blockstrmap[$this->_block_regcounterstr][0] = $matches[1];
        if(isset(
$matches[2])) $this->blockstrmap[$this->_block_regcounterstr][1] = $matches[2];
        
$this->blockstrmap[$this->_block_regcounterstr][2] = $this->block_counterstr;

        if(!empty(
$this->blockstrmap[$this->_block_regcounterstr][0])) $blockstrmap_temp "[{$this->blockstrmap[$this->_block_regcounterstr][0]}]";else $blockstrmap_temp ='';
        
$this->_set("n$_end{$this->_block_regcounterstr}=count($_nstem_blockvars[{$this->_block_regcounterstr}]{$blockstrmap_temp});nfor($_i{$this->_block_regcounterstr}=1;$_i{$this->_block_regcounterstr}<=$_end{$this->_block_regcounterstr};$_i{$this->_block_regcounterstr}++){n");
        
array_unshift($this->_reg_blocks$this->_block_regcounterstr);
        
    }
    
    function 
_process_blockend(){
        
$this->_block_reg--;
        
$this->_set("}");
        
array_shift($this->_reg_blocks);
    }
    
    function 
_process_if($expression$type 'if'){
        
preg_match_all('/((?:'|"|$|)s*[w]+s*(?:'|"|(|))/', $expression, $matches);
        
        foreach($matches[1] as $name => $value){
            $_value = trim($value);
            if(!preg_match('
/(?:^[0-9]+|^'|$|^\")|(?:($)|(?:true|false)/'$_value)){
                
                
$expression preg_replace('/'.preg_quote($value).'/'"$_nstem_vars['{$_value}']"$expression1);
            }
        }
        if(
$type == 'if'){
            
$this->_set("if({$expression}){");
        }else{
            
$this->_set("}elseif({$expression}){");
        }
    }

    function 
_process_static($varname){
        global $
$varname;
        
$this->source str_replace($this->_tokenstr, $$varname$this->source);
    }
    
    function 
_process_lang($varname){
        
$langvar $this->_langvar;
        global $
$langvar;
        
$lang = $$langvar;
        
$this->source str_replace($this->_tokenstr$lang[$this->conf['lang']][$varname], $this->source);
    }
    
    function 
_process_definelang($varname){
        
preg_match('/^$(.*?)$/'$varname$matches);
        
$this->_langvar $matches[1];
        
$this->source str_replace($this->_tokenstr''$this->source);
    }
    
    function 
_process_set($varname$value){
        if(
preg_match("/^'(.*)'$/"$value$matches)){
            
$_nstem_vars[$varname] = $matches[1];
            
$this->source str_replace($this->_tokenstr"<?php $_nstem_vars['{$varname}'] = '{$matches[1]}' ?>"$this->source);
        }else{
            
$_nstem_vars[$varname] = $_nstem_vars[$value];
            
$this->source str_replace($this->_tokenstr"<?php $_nstem_vars['{$varname}'] = $_nstem_vars['{$value}'] ?>"$this->source);
        }
    }
    
    function 
_process_vars($varname$first='block'){
        global 
$_nstem_blockvars,$_nstem_vars;
        
        if(!empty(
$this->_reg_blocks) && !empty($varname) && $first == 'block'){
            
$_current_blocks array_shift($this->_reg_blocks);
            
array_unshift($this->_reg_blocks$_current_blocks);
            
$_replace_tokenstr '/'.str_replace('/''/' preg_quote($this->_tokenstr)).'/';
            if(!empty(
$this->blockstrmap[$_current_blocks][0])) $blockstrmap_temp_0 "[{$this->blockstrmap[$_current_blocks][0]}]";else $blockstrmap_temp_0 "[{$this->blockstrmap[$_current_blocks][2]}]";
            if(!empty(
$this->blockstrmap[$_current_blocks][1])) $blockstrmap_temp_1 "[{$this->blockstrmap[$_current_blocks][1]}]";else $blockstrmap_temp_1 ='';
            
            
$this->source preg_replace($_replace_tokenstr"<?php echo isset($_nstem_blockvars[$_current_blocks]{$blockstrmap_temp_0}{$blockstrmap_temp_1}['{$varname}']) ? $_nstem_blockvars[$_current_blocks]{$blockstrmap_temp_0}{$blockstrmap_temp_1}['{$varname}'] : $_nstem_vars['{$varname}']; ?>"$this->source1);
        }elseif(!empty(
$varname)){
            
$_replace_tokenstr '/'.str_replace('/''/' preg_quote($this->_tokenstr)).'/';
            
$this->source preg_replace($_replace_tokenstr"<?php echo $_nstem_vars['{$varname}']; ?>"$this->source1);
        }
    }
}

?>
静态变量与多语言
===========================
代码====

<?php
include_once('nstemplate.php');

$lang['en']['1']='Test';
$lang['chs']['1']='测试静态';
$hhh 'aaa';

$tpl = new template('testtpl.txt', array('lang' => 'en'));

$tpl->push();
?>
模板====

QUOTE:
<!--# {definelang:$lang}#-->
{lang:1}
{static:hhh}
===========================

嵌套与循环
===========================
代码====

<?php
include_once('nstemplate.php');
$t = new Template('testtpl.txt');
$t->setblocks("1","2");
$t->setblocks("2","3");
for (
$k=0;$k<2;$k++){
$t->block("3");  
$t->assign("for3","循环3");
$t->processblock(); 
for (
$i=