Chinaunix首页 | 论坛 | 博客
  • 博客访问: 802614
  • 博文数量: 42
  • 博客积分: 10080
  • 博客等级: 上将
  • 技术积分: 1970
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-06 23:06
文章存档

2011年(1)

2010年(7)

2009年(4)

2008年(30)

我的朋友

分类:

2008-09-15 01:17:10

模板类,有些地方不方便看,拷贝到你的编辑器看吧

<?php
/**
 * 模板类
 *
 * @category XD
 * @package XD_View
 * @copyright Copyright (c) 2008
 * @license New BSD License
 * @version $Id: XD/View.php 版本号 2008-09-03 02:06:xx epaddy $
 */

require_once 'XD/View/Exception.php';

/**
 * 视图
 *
 *
 */

final class XD_View {
    public $force = 0; // 是否每次都编译模板

    public $merge = 0; // 是否合并模板


    private $_language = array();
    private $_tplDir = 'view/default';
    private $_compliedDir = 'data/view';
    
    private $_tplFile = '';
    private $_compliedFile = '';
    private $_vars = array();
    private $_tplId = '';

    const VAR_REGEXP = "(\@?\\\$[a-zA-Z_][\\\$\w]*(?:\[[\w\-\.\"\'\[\]\$]+\])*)";
    const CONST_REGEXP = "/\{([\w]+)\}/";

    public function __construct() {
    }
    
    public function setTplDir($dir) {
        $this->_tplDir = trim($dir, '/');
    }
    
    public function setCompliedDir($dir) {
        $this->_compliedDir = trim($dir, '/');
    }

    /**
     * 设置语言,将把$this->_language覆盖掉
     *
     * @param array $lang 语言数组
     */

    public function setLang($lang) {
        $this->_language = (array)$lang;
    }

    /**
     * 添加语言项
     *
     * @param array $lang
     */

    public function addLang($lang) {
        $this->_language = array_merge($this->_language, (array)$lang);
    }

    /**
     * 模板变量赋值
     *
     * @param string $k 模板变量下标
     * @param mixed $v 模板变量值
     */

    public function assign($k, $v) {
        $this->_vars[$k] = $v;
    }

    /**
     * 显示文件
     *
     * @param string $file 模板文件
     */

    public function display($file, $tplId = '') {
        $this->_tplId = $tplId;
        extract($this->_vars, EXTR_SKIP);
        include $this->_getTpl($file);
    }

    /**
     * 获取模板
     *
     * @param string $file 模板文件名
     * @return string 编译后的模板文件
     */

    private function _getTpl($file) {
        $this->_tplFile = BASE_DIR . "/{$this->_tplDir}/{$file}.htm";
        $this->_compliedFile = BASE_DIR . "/{$this->_compliedDir}/{$this->_tplId}_{$file}.php";

        // 判断是否强制编译或是否过期($this->_compliedFile不存在时 < 成立)

        if($this->force || @filemtime($this->_compliedFile) < @filemtime($this->_tplFile)) {
            $this->_complie();
        }

        return $this->_compliedFile;
    }

    /**
     * 编译模板
     *
     * @throws XD_View_Exception 如果模板文件不存在则抛出异常
     *
     */

    private function _complie() {
        if(!$template = file_get_contents($this->_tplFile)) {
            throw new XD_View_Exception($this->_tplFile . ' does not exists!');
        }
        // 包含另一个模板

        // {tpl xx}

        $template = preg_replace("/\{tpl\s+['\"]?(.*?)['\"]?\}/ise", "\$this->_subTpl('\\1')", $template);
        
        // 去掉

        $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
        
        // 处理语言

        // {lang key} {lang key1 key2}

        $template = preg_replace("/\{lang\s+(\w+?)\s+(\w+?)\}/ise", "\$this->_lang('\\1', '\\2')", $template);
        $template = preg_replace("/\{lang\s+(\w+?)\}/ise", "\$this->_lang('\\1')", $template);
        
        // 把php代码块进行base64编码,使其中的变量不被处理

        // {#xx#}

        $template = preg_replace("/\{#(.+?)#\}/ies", "'{base64 ' . base64_encode('\\1') . '}'", $template);
        
        // 处理变量

        // {$var}

        $template = preg_replace("/\{" . self::VAR_REGEXP . "\}/", "", $template);

        // {if 表达式}

$template = preg_replace("/\{if\s+(.+?)\}/is", "", $template);        
        // {elseif 表达式}
        $template = preg_replace("/\{elseif\s+(.+?)\}/is", "", $template);
        // {else}
        $template = preg_replace("/\{else\}/is", "", $template);
        // {for 表达式1; 表达式2; 表达式3}
        $template = preg_replace("/\{for\s+(.*?)\}/is", "", $template);
        
        // endif
        // {/if}
        $template = preg_replace("/\{\/if\}/is", "", $template);
        // endfor
        // {/for}
        $template = preg_replace("/\{\/for\}/is", "", $template);

        // foreach
        for($i=0; $i<5; $i++) {
            // {loop $xx $xx}
            $template = preg_replace("/\{loop\s+" . self::VAR_REGEXP . "\s+" . self::VAR_REGEXP . "\s+" . self::VAR_REGEXP . "\}(.+?)\{\/loop\}/ies", "\$this->_loopSection('\\1', '\\2', '\\3', '\\4')", $template);
            // {loop $xx $xx $xx}
            $template = preg_replace("/\{loop\s+" . self::VAR_REGEXP . "\s+" . self::VAR_REGEXP . "\}(.+?)\{\/loop\}/ies", "\$this->_loopSection('\\1', '', '\\2', '\\3')", $template);
        }

        // {CONST}
        $template = preg_replace(self::CONST_REGEXP, "", $template);// {else} 也符合常量格式,这必须要在{else}后面
        
        $template = preg_replace("/\{base64\s(.+?)\}/ise", "''", $template); // 还原页面中的php脚本
        $template = preg_replace("/(\\\$[a-zA-Z_]\w+\[)([a-zA-Z_]\w+)\]/i", "\\1'\\2']", $template); // $x[x] => $x['x']
        
        // {url xx}
        $template = preg_replace("/\{url\s+['\"]?(.*?)['\"]?\}/is", "_url(\"\\1\");?>", $template);

        $template = str_replace('?>, "\r\n", $template);

        // 添加在模板顶部的信息

        $thisTplMsg = ";
        $thisTplMsg.= " * XD Web App Framework Template\r\n";
        $thisTplMsg.= " *\r\n";
        $thisTplMsg.= " * made file: {$this->_compliedFile}\r\n";
        $thisTplMsg.= " * make from: {$this->_tplFile};\r\n";
        $thisTplMsg.= " * make time: ". microtime(1) . ";\r\n";
        $thisTplMsg.= " * make by XD template engine at " . date('Y-m-d H:i:s') . "\r\n";
        $thisTplMsg.= " */\r\n";
        $thisTplMsg.= "if(!defined('XD_IN')) exit('Access Denied');\r\n";
        $thisTplMsg.= "?>";

        $template = $thisTplMsg . $template;

        $fp = fopen($this->_compliedFile, 'w');
        flock($fp, LOCK_EX);
        fwrite($fp, $template);
        flock($fp, LOCK_UN);
        fclose($fp);
    }

    private function _loopSection($arr, $k, $v, $statement) {
        $statement = str_replace("\\\"", '"', $statement);
        return $k ? "$v) :?>$statement" : "$statement";
    }

    /**
     * 语言包处理
     *
     * @param string $k1 下标1
     * @param string $k2 下标2
     * @return string 语言包中该数组变量的值
     */
    private function _lang($k1, $k2 = null) {
        if ($k2) {
            return !empty($this->_language[$k1][$k2]) ? $this->_language[$k1][$k2] : "{ {$k1}-{$k2} }";
        } else {
            return !empty($this->_language[$k1]) ? $this->_language[$k1] : "{ $k1 }";
        }
    }
    
    private function _url($url){
        if($GLOBALS['config']['clearUrl']) {
            return XD_Util_Encoder::encode($url) . '.htm';
        } else {
            return '?' . $url;
        }
    }

    private function _subTpl($subTpl) {
        if ($this->merge) {
            $content = file_get_contents(BASE_DIR . "/{$this->_tplDir}/{$subTpl}.htm");
            // 多级包含,尽管支持多级包含,但应该不用多级包含
            for ($i=0; $i<5; $i++) {
                $content = preg_replace("/\{tpl\s+['\"]?(.*?)['\"]?\}/ise", "file_get_contents(BASE_DIR . \"/{$this->_tplDir}/\\1.htm\")", $content); // {tpl xx}
            }
            return $content;
        } else {
            return "_getTpl('{$subTpl}');?>";
        }
    }
}

阅读(1161) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~