<?php
/*
系统核心模板类
模板支持静态化, 模板表单安全验证, 模板可直接调用验证码, COOKIE, SESSION, 所有常用标签解析(一定程度上支持嵌套, 逻辑判断), 模板扩展标签解析, 模板插件(函数直接调用), 并做了几个常用系统函数标签, 模板局部静态化, 模板一次性编译, 模板缓存生存时间限制, 模板缓存清除(自动清除和手工清除均支持, 手工指定模板是否缓存), 模板可控制是否与php代码嵌套, 模板布局渲染(页面首尾分离, 可手工指定不分离), 更多配置, 可在配置文件中选择
*/
defined("IN_SHOP") or die();
class Tpl {
protected $template_dir = 'tmp/template/'; //模板目录
protected $compile_dir = 'tmp/compile/'; //模板编译目录
protected $left_delimiter = '{'; //模板解析标识符
protected $right_delimiter = '}';
protected $tpl_suffix = '.html'; //模板后缀, 与静态页面后缀保持一致
protected $cpl_prefix = ''; //模板编译文件前缀
protected $max_cache_time = 0; //模板最大缓存时间(0默认永久缓存, 以后可在后台手工清除缓存, 或者在系统常量中定义最大缓存时间)
protected $make_cache = false; //是否开启模板编译缓存
protected $max_make_time = 0; //模板最大编译缓存时间(0默认永久缓存)
protected $is_cache = false; //是否开启模板缓存(模板整体静态化)
protected $cache_dir = 'tpl_caches'; //模板缓存目录
protected $_var = array(); //assign变量
protected $form_hash = ''; //模板表单随机码, 防止跨域提交(模板静态化时, 该功能将关闭)
protected $layout = false; //是否开启布局渲染, 后台一般不需要启用模板布局
protected $layout_dir = 'layout'; //模板布局目录
protected $layout_file = 'layout.html'; //模板布局文件(格式 header {$layout} footer)
protected $tpl_char = 'utf-8'; //默认模板编码格式
protected $tpl_php = true; //是否允许模板中内嵌PHP代码
protected $tpl_extends_dir = 'tpl_extends'; //模板扩展目录
protected $tpl_plugins_file = 'tpl_plugins.php'; //模板插件文件
protected $tag_extends_file = 'tag_extends_file'; //自定义扩展标签解析文件
protected $tag = array(
/* notice: 请严格按照标签示例写 */
/* 标签解析规则 $key:标签名, attr:标签属性, level:允许标签嵌套层次 function: 标签函数 */
'var' => array('function' => '_var'), //普通一维数组
'include' => array('function' => '_include'), //css文件引入
'insert' => array('function' => '_insert'), //js文件引入
'foreach' => array('level' => 3, 'function' => '_foreach'),
'if' => array('function' => '_if'),
'tag_note' => array('function' => 'tag_note'), //模板注释标签
'date' => array('function' => '_date'), //返回当前时间
'session' => array('function' => '_session'), //session标签处理
'cookie' => array('function' => '_cookie'), //cookie标签处理
'cache' => array('function' => '_cache'), //局部缓存标签
'captcha' => array('function' => '_captcha'), //验证码标签(可直接生成验证码)
'for' => array('attr' => array(
'start' => 0, /* 默认从0开始循环, 最多循环10次, 步长为1 */
'stop' => 10,
'step' => 1,
), 'level' => 2, 'function' => '_for'),
/* 系统函数标签 */
'substr' => array('function' => '_substr'),
'english_str' => array('attr' => array(
'ucfirst', 'strtolower', 'strtoupper', //英文字符串处理
),'function' => 'english_str'),
/* 插件调用 */
'function' => array('function' => '_function'),
/* 自定义扩展标签解析 */
'extends' => array('function' => '_extends'),
);
function __construct($tpl_dir = '', $cpl_dir = '', $cache_dir = '') {
/*
可以控制前后台模板目录, 编译目录和缓存目录的不同位置
*/
if ($tpl_dir)
{
$this->template_dir = $tpl_dir;
if (!is_dir($this->template_dir))
@mkdir($this->template_dir, 0755, true);
}
else
{
$this->template_dir = ROOT_PATH . $this->template_dir;
if (!is_dir($this->template_dir))
@mkdir($this->template_dir, 0755, true);
}
if ($cpl_dir)
{
$this->compile_dir = $cpl_dir;
if (!is_dir($this->compile_dir))
@mkdir($this->compile_dir, 0755, true);
}
else
{
$this->compile_dir = ROOT_PATH . $this->template_dir;
if (!is_dir($this->compile_dir))
@mkdir($this->compile_dir, 0755, true);
}
if (TAG_LEFT)
$this->left_delimiter = TAG_LEFT;
if (TAG_RIGHT)
$this->right_delimiter = TAG_RIGHT;
if (TPL_CACHE)
$this->is_cache = TPL_CACHE;
if (MAX_TPL_CACHE)
$this->max_cache_time = MAX_TPL_CACHE;
if ($cache_dir)
{
$this->cache_dir = $cache_dir;
if (!is_dir($this->cache_dir))
@mkdir($this->cache_dir, 0755, true);
}
if (TPL_SUFFIX)
$this->tpl_suffix = TPL_SUFFIX;
if (CPL_PREFIX)
$this->cpl_prefix = CPL_PREFIX;
if (TPL_HASH)
$this->form_hash = md5($this->template_dir . $this->compile_dir . date('YmdHis', time()) . rand(1000, 10000));
if (MAKE_CACHE)
$this->make_cache = MAKE_CACHE;
if (TPL_EXTENDS_DIR)
{
$this->tpl_extends_dir = ROOT_PATH . '/' .TPL_EXTENDS_DIR . '/';
if (!is_dir($this->tpl_extends_dir))
@mkdir($this->tpl_extends_dir);
}
if (TPL_PLUGINS_FILE)
{
$this->tpl_plugins_file = $this->tpl_extends_dir . TPL_PLUGINS_FILE;
if (!file_exists($this->tpl_plugins_file))
@touch($this->tpl_plugins_file);
}
if (TAG_EXTENDS_FILE)
{
$this->tag_extends_file = $this->tpl_extends_dir . TAG_EXTENDS_FILE;
if (!file_exists($this->tag_extends_file))
@touch($this->tag_extends_file);
}
if (LAYOUT_ON)
{
$this->layout = LAYOUT_ON;
if(LAYOUT_DIR)
$this->layout_dir = ROOT_PATH . LAYOUT_DIR . '/';
else
$this->layout_dir = ROOT_PATH . $this->layout_dir . '/';
if (!is_dir($this->layout_dir))
@mkdir($this->layout_dir, 0755, true);
if (LAYOUT_FILE)
$this->layout_file = $this->layout_dir . LAYOUT_FILE;
else
$this->layout_file = $this->layout_dir . $this->layout_file;
}
if (MAX_MAKE_TIME)
$this->max_make_time = MAX_MAKE_TIME;
if (SHOP_CHARSET)
$this->tpl_char = SHOP_CHARSET;
if (!TPL_PHP)
$this->tpl_php = TPL_PHP;
header('Content-Type: text/html;charset=' . $this->tpl_char); //模板默认字符集
}
/*
模板变量赋值
@parmas $name string 模板变量名
$value mixed 模板变量值(暂时不能接受对象, 资源)
*/
function assign($name, $value = '') {
$this->_var[$name] = $value;
}
/*
手动指定模板是否缓存
*/
function display($file, $is_cache = true, $layout = true) {
//手工控制是否缓存
$this->tpl_cache = !$is_cache ? $is_cache : !$is_cache;
//生成静态文件名
$static_file = $this->cache_dir . $file . $this->tpl_suffix;
//生成编译文件名, 唯一文件
$make_name = $this->cpl_prefix . md5($this->compile_dir . $file) . '.php';
$make_file = $this->compile_dir . $make_name;
//DEBUG模式下不启用静态缓存文件
if ($this->is_cache && DEBUG)
{
if (file_exists($static_file) && (filesize($static_file) > 0))
{
//检测静态文件是否过期
if ($this->max_cache_time > 0)
{
if (!$this->check_file($static_file))
{
//静态文件未过期
include ($static_file);
exit();
}
else
{
@unlink($static_file);
}
}
else
{
include ($static_file);
exit(); //永久缓存, 除非手工清除
}
}
else
{
//如果不存在检测编译文件是否存在, 如果存在则一并删除
if (file_exists($make_file))
@unlink($make_file);
}
}
//检测编译文件是否存在, 如何存在则直接使用, 不用再编译
if (file_exists($make_file) && $this->make_cache && (filesize($make_file) > 0))
{
//检测文件是否过期
if ($this->max_make_time > 0)
{
if (!$this->check_file($make_file, 'make'))
{
//编译未过期, 对其静态化
include ($make_file);
exit();
}
else
{
//删除编译文件
@unlink($make_file);
}
}
else //编译文件永久缓存
{
include ($make_file);
exit();
}
}
$file = $this->template_dir . $file . $this->tpl_suffix;
//检测模板是否存在
if (!file_exists($file))
{
return $this->tpl_exception('模板异常: 模板不存在, 错误行号: ' . __LINE__);
}
//解析模板
$out = $this->fetch($file, $layout);
//生成编译文件
if ($this->make_cache)
$this->make_file($make_file, $out);
//模板内容输出
echo $content = $this->_eval($out);
//模板静态化, DEBUG模式下不缓存
if ($this->tpl_cache && !DEBUG)
{
$this->static_file($static_file, $content);
}
}
/*
生成模板编译文件
*/
protected function make_file($file, $content) {
@file_put_contents($file, $content, LOCK_EX);
}
/*
模板静态化
*/
protected function static_file($file, $content) {
@file_put_contents($file, $content);
}
/*
检测文件是否过期, 如果过期返回true
*/
protected function check_file($file, $type = 'static') {
if ((time() - filectime($file)) > $this->max_cache_time && $type == 'static')
return true;
elseif ((time() - filectime($file)) > $this->max_make_time && $type == 'make')
return true;
return false;
}
function fetch($file, $layout = true) {
$content = file_get_contents($file);
// 判断是否开启模板布局
if ($this->layout && file_exists($this->layout_file) && $layout)
{
$layout = file_get_contents($this->layout_file);
$content = preg_replace('/\{\$layout\}/', $content, $layout);
}
//解析之前, 判断是否允许模板内嵌PHP代码
if (!$this->tpl_php)
{
$content = preg_replace('/\<\?php.*?\?\>/i', '', $content);
}
//去除编译文件中所有的换行, 增加编译代码执行效率
$content = $this->_trim($content);
//开始解析标签
//最先解析所有模板注释标签
if (preg_match('/\\' . $this->left_delimiter . '\\*\*\*.*\*\*\*\\' . $this->right_delimiter . '/', $content, $res))
{
$content = $this->tag_resolving('tag_note', $content);
}
//普通标签解析
preg_match_all('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\\'. $this->right_delimiter . '/i', $content, $tag); //匹配变量标签
if (!empty($tag[0]))
$content = $this->_var($tag, $content); //普通标签处理
//include标签解析
if (preg_match('/\\' . $this->left_delimiter . '(include)\s+file\=.*\s+type\=css\s+\/\\' . $this->right_delimiter . '/is', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//insert标签解析
if (preg_match('/\\' . $this->left_delimiter . '(insert)\sfile\=.*\stype\=javascript\s\/\\' . $this->right_delimiter . '/i', $content, $tag)) {
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//foreach标签解析
if (preg_match('/\\' . $this->left_delimiter . '(foreach)\s+from/i', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
if (preg_match('/\\' . $this->left_delimiter . '(foreach)\s\.*\\' . $this->right_delimiter . '.*\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $tag))
{ echo 123;
}
//for标签解析
if (preg_match('/\\' . $this->left_delimiter . '(for).*\\' . $this->right_delimiter . '.*\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/is', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//if标签解析
if (preg_match('/\\' . $this->left_delimiter . '(if).*\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/if\\' . $this->right_delimiter . '/is', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//substr标签
if (preg_match('/\\' . $this->left_delimiter . '\$.*?\:\s+_(substr)\([0-9]+\,\s{0,}[0-9]+\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
$content = $this->tag_resolving($tag[1], $content);
}
/* english_str标签 */
//ucfirst
if (preg_match('/\\' . $this->left_delimiter . '\\$.*?\:\s+_(ucfirst)\(\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
$function = $this->tag['english_str']['function'];
$content = $this->$function($content, $tag[1]);
}
//strtolower
if (preg_match('/\\' . $this->left_delimiter . '\\$.*?\:\s+_(strtolower)\(\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
$function = $this->tag['english_str']['function'];
$content = $this->$function($content, $tag[1]);
}
//strtolupper
if (preg_match('/\\' . $this->left_delimiter . '\\$.*?\:\s+_(strtoupper)\(\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
$function = $this->tag['english_str']['function'];
$content = $this->$function($content, $tag[1]);
}
//解析date标签
if (preg_match('/\\' . $this->left_delimiter . '_(date)\(\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//session标签解析
if (preg_match('/\\' . $this->left_delimiter . '\$_(SESSION)\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $tag))
{
$session = strtolower($tag[1]);
if (array_key_exists($session, $this->tag))
{
$content = $this->tag_resolving($session, $content);
}
}
//cookie标签解析
if (preg_match('/\\' . $this->left_delimiter . '\$_(COOKIE)\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $tag))
{
$session = strtolower($tag[1]);
if (array_key_exists($session, $this->tag))
{
$content = $this->tag_resolving($session, $content);
}
}
//插件解析
if (preg_match('/\\' . $this->left_delimiter . '(function)\:\s+[a-zA-Z0-9_]+\(\)\\' . $this->right_delimiter . '/i', $content, $tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
//自定义标签解析
if (preg_match('/\\' . $this->left_delimiter . '(extends)\:\s+[a-zA-Z0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/extends\:\s+[a-zA-Z0-9]+\\' . $this->right_delimiter . '/i', $content, $tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
//普通数组标签解析
if (preg_match('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', $content, $tag))
{
$content = $this->_array_var($content);
}
//验证码标签解析
if (preg_match('/\{(captcha).*\/\}/i', $content, $tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
//cache标签解析, 该标签最后解析
if (preg_match('/\\' . $this->left_delimiter . '(cache)\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/cache\\' . $this->right_delimiter . '/i', $content, $tag))
{
if (array_key_exists($tag[1], $this->tag))
{
$content = $this->tag_resolving($tag[1], $content);
}
}
//表单hash串生成, 模板静态化时, 不生成表单随机码
if ($this->form_hash != '' && !$this->tpl_cache)
{
$content = $this->_hash($content);
}
return $content;
}
/*
模板异常处理
*/
protected function tpl_exception($msg) {
try{
throw New Exception($msg); //抛出异常
}
catch(Exception $e)
{
echo $e->getMessage();
}
return;
}
/*
PHP代码可执行函数
*/
protected function _eval($str) {
if ($this->is_cache)
{
ob_start();
eval('?>' . trim($str));
$content = ob_get_contents();
ob_end_clean();
return $content;
}
else
{
return eval('?>' . trim($str));
}
}
/*
去除模板编译后文件的所有换行
*/
protected function _trim($str) {
return preg_replace('/[\r]+|[\n]+|[\r\n]+/', '', $str);
}
/*
标签解析调用方法
*/
protected function tag_resolving($tag, $content) {
$function = $this->tag[$tag]['function'];
return $this->$function($content);
}
/*
*************************************
*************************************
标签解析函数
*************************************
*************************************
*/
/*
注释标签
example: {*** 注释内容 ***}
notice: 注释标签率先解析, 将注释掉所包含的所有代码(包括html, js, css代码)
*/
protected function tag_note($content) {
$content = preg_replace('/\\' . $this->left_delimiter . '\*\*\*.*?\*\*\*\\' . $this->right_delimiter . '/', '', $content);
return $content;
}
/*
普通标签处理 example: {$content}
@params $tag array 匹配到的标签
$content string 文本内容
*/
protected function _var($tag, $content) {
foreach ($tag[1] as $v)
{
if (array_key_exists($v, $this->_var))
{
//对数据普通变量进行匹配
$content = preg_replace('/\\' . $this->left_delimiter . '\$' . $v . '\\' . $this->right_delimiter . '/', '<?php echo $this->_var["' . $v .'"]; ?>', $content);
}
}
return $content;
}
/*
include标签 example: {include file=type.css type=css /}
notice: 可以引入多个文件{include file=type.css my.css type=css /}
*/
protected function _include($content) {
//替换单个文件
$content = preg_replace('/\\' . $this->left_delimiter . 'include\s+file\=([a-zA_Z0-9_\.\/\:]+)\s+type\=css\s+\/\\' . $this->right_delimiter . '/i', '<style rel="stylesheet" type="text/css" href="\1"></style>', $content);
//替换多个文件
if (preg_match_all('/\\' . $this->left_delimiter . 'include\s+file\=([a-zA_Z0-9_\.\:]+\,){1,}[a-zA_Z0-9_\.\:]+\s+type\=css\s+\/\\' . $this->right_delimiter . '/i', $content, $res))
{
$include = '';
foreach ($res[0] as $r)
{
$str[] = substr($r, 13, -11);
}
foreach ($str as $s)
{
$arr = explode(',', $s);
foreach ($arr as $a)
{
$include .= '<style rel="stylesheet" tpye="text/css" href="' . $a .'"></style>';
}
}
$content = preg_replace('/\\' . $this->left_delimiter . 'include\sfile\=([a-zA_Z0-9_\.\:]+\,){1,}[a-zA_Z0-9_\.\:]+\stype\=css\s\/\\' . $this->right_delimiter . '/i', $include, $content);
}
return $content;
}
/*
insert标签 example: {insert file=type.js type=js /}
notice: 可以引入多个文件
*/
function _insert($content) {
//引入单个文件
$content = preg_replace('/\\' . $this->left_delimiter . 'insert\sfile\=([a-zA-Z0-9_\.\:]+)\stype\=javascript\s\/\\' . $this->right_delimiter . '/i', '<script type="text/javascript" src="\1"></script>', $content);
//引入多个文件
if (preg_match_all('/\\' . $this->left_delimiter . 'insert\sfile\=([a-zA-Z0-9_\.\:]+\,){1,}[a-zA_Z0-9_\.\:]+\stype\=javascript\s\/\\' . $this->right_delimiter . '/i', $content, $res))
{
$insert = '';
foreach ($res[0] as $r)
{
$str[] = substr($r, 13, -18);
}
foreach ($str as $s)
{
$arr = explode(',', $s);
foreach ($arr as $a)
{
$insert .= '<script type="text/javascript" src="' . $a . '"></script>';
}
}
$content = preg_replace('/\\' . $this->left_delimiter . 'insert\sfile\=([a-zA-Z0-9_\.\:]+\,){1,}[a-zA_Z0-9_\.\:]+\stype\=javascript\s\/\\' . $this->right_delimiter . '/i', $insert, $content);
}
return $content;
}
/*
for循环标签
example: {for star=0 stop=100 step=1}循环体{$start}{/for}----{$start}为模板引擎关键词$i, 请勿在for标签循环体外使用
notice: 只默认一层循环, 最多支持两层循环, 可在标签规则中设定level级别
*****************双层for标签不支持**********************
单层标签如果使用$i(初始变量) {for start=[$i=0] stop=100 step=1}{/for}
*/
protected function _for($content) {
/* 解析顺序: 从多到少解析, 防止解析冲突 notice: 标签嵌套初始值, 最终值, 步长请自定义, 没有配置level默认只解析一层标签 */
//解析双层for标签
if ($this->tag['for']['level'] == 2)
{
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\s+stop\=[0-9_]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\s+stop\=[0-9_]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '.*\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/(\{for\s+start\=([0-9]+)\s+stop\=([0-9_]+)\s+step\=([0-9]+)\}).*?(\{for\s+start\=([0-9]+)\s+stop\=([0-9_]+)\s+step\=([0-9]+)\}).*?\{\/for\}.*?\{\/for\}/i', $content, $res);
//解析for标签
foreach ($res[1] as $k => $v)
{
$content = str_replace($v, '<?php for($i=' . $res[2][$k] . ';$i<' . $res[3][$k] . ';$i=$i+' . $res[4][$k] . '){ ?>', $content);
}
}
}
/* 解析单层标签 */
if (preg_match('/\\' . $this->left_delimiter . 'for.*?\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/is', $content, $res))
{
//默认单层标签循环10次
if (preg_match('/\\' . $this->left_delimiter . 'for\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\\' . $this->right_delimiter . '/is', '<?php for($i=' . $this->tag['for']['attr']['start'] . ';$i<' . $this->tag['for']['attr']['stop'] . ';$i++){ ?>', $content);
}
//只指定start
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for($i=\1;$i<' . $this->tag['for']['attr']['stop'] . ';$i++){ ?>', $content);
}
//只指定stop
if (preg_match('/\\' . $this->left_delimiter . 'for\s+stop\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+stop\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for($i=' . $this->tag['for']['attr']['start'] . ';$i<\1;$i++){ ?>', $content);
}
//只指定step
if (preg_match('/\\' . $this->left_delimiter . 'for\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+step=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for($i=' . $this->tag['for']['attr']['start'] . ';$i<' . $this->tag['for']['attr']['stop'] . ';$i=$i+\1){ ?>', $content);
}
//指定start, 并在循环体内调用start
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=\[\$[a-zA-Z_]+\=[0-9]+\]\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\\' . $this->right_delimiter . '/i', $content, $res);
//先解析start
foreach ($res[1] as $k => $v)
{
$content = str_replace($this->left_delimiter . $v . $this->right_delimiter, '<?php echo ' . $v . '; ?>', $content);
}
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\\' . $this->right_delimiter . '/i', '<?php for(\1=\2;$1<' . $this->tag['for']['attr']['stop'] . ';\1++){ ?>', $content);
}
//指定start 和 stop
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\s+stop\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\{for\s+start\=([0-9]+)\s+stop\=([0-9]+)\}/i', '<?php for($i=\1;$i<\2;$i++){ ?>', $content);
}
//指定start 和 step
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=([0-9]+)\s+step\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for($i=\1;$i<' . $this->tag['for']['attr']['stop'] . ';$i=$i+\2){ ?>', $content);
}
//指定stop 和 step
if (preg_match('/\\' . $this->left_delimiter . 'for\s+stop\=[0-9]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+stop\=([0-9]+)\s+step\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for($i=' . $this->tag['for']['attr']['start'] . ';$i<\1;$i=$i+\2){ ?>', $content);
}
//指定start 和 stop 并使用start变量
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=\[\$[a-zA-Z_]+\=[0-9]+\]\s+stop\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\s+stop\=([0-9]+)\\' . $this->right_delimiter . '/i', $content, $res);
foreach ($res[1] as $k => $v)
{
$content = str_replace($this->left_delimiter . $v . $this->right_delimiter, '<?php echo ' . $v .'; ?>', $content);
}
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\s+stop\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for (\1=\2;\1<\3;\1++){ ?>', $content);
}
//指定start 和 step 并使用start变量
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=\[\$[a-zA-Z_]+\=[0-9]+\]\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\s+step\=([0-9]+)\\' . $this->right_delimiter . '/is', $content, $res);
foreach ($res[1] as $k => $v)
{
$content = str_replace($this->left_delimiter . $v . $this->right_delimiter, '<?php echo ' . $v .'; ?>', $content);
}
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z_]+)\=([0-9]+)\]\s+step\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for (\1=\2;\1<' . $this->tag['for']['attr']['stop'] . ';\1=\1+\3){ ?>', $content);
}
//指定start stop step
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=[0-9]+\s+stop\=[0-9]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=([0-9]+)\s+stop\=([0-9]+)\s+step\=([0-9]+)\\' . $this->right_delimiter . '/i','<?php for($i=\1;$i<\2;$i=$i+\3){ ?>', $content);
}
//指定start 并调用$start
if (preg_match('/\\' . $this->left_delimiter . 'for\s+start\=\[\$[a-zA-Z0-9]+\=[0-9]+\]\s+stop\=[0-9]+\s+step\=[0-9]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z0-9]+)\=([0-9]+)\]\s+stop\=([0-9]+)\s+step\=([0-9]+)\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/i', $content, $res);
foreach ($res[1] as $k => $v)
{
$content = str_replace($this->left_delimiter . $v . $this->right_delimiter, '<?php echo ' . $v .'; ?>', $content);
}
$content = preg_replace('/\\' . $this->left_delimiter . 'for\s+start\=\[(\$[a-zA-Z0-9]+)\=([0-9]+)\]\s+stop\=([0-9]+)\s+step\=([0-9]+)\\' . $this->right_delimiter . '/i', '<?php for(\1=\2;\1<\3;\1=\1+\4){ ?>', $content);
}
}
//解析所有for标签结束标签
$content = preg_replace('/\\' . $this->left_delimiter . '\/for\\' . $this->right_delimiter . '/is', '<?php } ?>', $content);
return $content;
}
/*
二维数组解析
foreach 标签
example: {foreach from=$arr key=$key item=$value}({$value.value} or {$value.0(下标)}){key.$key}{/foreach} or {foreac from=$arr item=$value}{$value.value}{/foreach}
notice: 标签可以嵌套, 默认最多嵌套三层(请注意key标签的用法)
*/
protected function _foreach($content) {
/* 解析顺序: 从多到少解析, 防止解析冲突 notice: 标签嵌套不解析$key, 没有配置level默认最多解析双层标签 */
if ($this->tag['foreach']['level'] == 3)
{
//解析三层标签
if ( preg_match('/(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ')/i', $content, $res))
{
preg_match_all('/(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-z-A-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . ')/i', $content, $res);
if (array_key_exists($res[2][0], $this->_var))
{
foreach ($res[1] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[2][$k] .'"] as ' . $res[3][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
if (array_key_exists($res[5][0], $this->_var))
{
foreach ($res[4] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[5][$k] .'"] as ' . $res[6][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
if (array_key_exists($res[8][0], $this->_var))
{
foreach ($res[7] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[8][$k] .'"] as ' . $res[9][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
}
}
//解析双层标签
if (preg_match('/\\' . $this->left_delimiter . 'foreach\s+from\=\$[a-zA-Z0-9_]+\s+item\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . 'foreach\s+from\=\$[a-zA-Z0-9_]+\s+item\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-zA-Z0-9_]+)\\' . $this->right_delimiter . ').*?(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-zA-Z0-9_]+)\\' . $this->right_delimiter . ').*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res);
if (array_key_exists($res[2][0], $this->_var))
{
foreach ($res[1] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[2][$k] . '"] as ' . $res[3][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
if (array_key_exists($res[5][0], $this->_var))
{
foreach ($res[4] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[5][$k] . '"] as ' . $res[6][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
}
/* 解析单层标签 */
//无$key时
if (preg_match('/\\' . $this->left_delimiter . 'foreach\s+from\=\$[a-zA-Z0-9_]+\s+item\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9_]+)\s+item\=(\$[a-zA-Z0-9_]+)\\' . $this->right_delimiter . ').*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res);
if (array_key_exists($res[2][0], $this->_var))
{
foreach ($res[1] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[2][$k] .'"] as ' . $res[3][$k] . '){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
}
//有$key时
if (preg_match('/\\' . $this->left_delimiter . 'foreach\s+from\=\$[a-zA-Z0-9]+\s+key\=\$[a-zA-Z0-9_]+\s+item\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res))
{
preg_match_all('/(\\' . $this->left_delimiter . 'foreach\s+from\=\$([a-zA-Z0-9]+)\s+key\=(\$[a-zA-Z0-9_]+)\s+item\=(\$[a-zA-Z0-9_]+)\\' . $this->right_delimiter . ').*?\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', $content, $res);
if (array_key_exists($res[2][0], $this->_var))
{
foreach ($res[1] as $k => $v)
{
$content = str_replace($v, '<?php foreach ($this->_var["' . $res[2][$k] . '"] as ' . $res[3][$k] .'=>' . $res[4][$k] .'){ ?>', $content);
}
}
else
{
return $this->tpl_exception('模板变量异常: value未定义, 错误行号: ' . __LINE__);
}
//解析标签中的{key.$key} 键值
if (preg_match('/\\' . $this->left_delimiter . 'key\.\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'key\.(\$[a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php echo \1; ?>', $content);
}
}
//解析标签中的数组变量
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\.[a-zA-Z0-9]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '(\$[a-zA-Z0-9_]+)\.([a-zA-Z0-9]+)\\' . $this->right_delimiter . '/i', '<?php echo \1["\2"]; ?>', $content);
}
//解析闭合标签{/foreach}
$content = preg_replace('/\\' . $this->left_delimiter . '\/foreach\\' . $this->right_delimiter . '/i', '<?php } ?>', $content);
return $content;
}
/*
if标签 example: {if $value(!$value)}{/if} {if $value(!$value)}{elseif}{/if} {if $value}{else}{/if}
notice: 默认最多支持两层嵌套
*/
protected function _if($content) {
/* 解析顺序: 先解析{if} 再解析{elseif} 最后解析{/if}*/
/* notice: if条件中可放入一维数组的键值形式 */
/* {if}标签 */
//{if $value}, $value为普通变量
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]){ ?>', $content);
}
//{if !$value}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if(!$this->_var["\1"]){ ?>', $content);
}
//{if $value[key]}, 放入普通一维数组
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]["\2"]){ ?>', $content);
}
//{if !$value[key]}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/is', '<?php if(!$this->_var["\1"]["\2"]){ ?>', $content);
}
/* 条件比较只支持普通变量比较, 如果要进行一维数组比较, 可在模板赋值时, 直接传入具体数组值 */
//{if $value1==$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]==$this->_var["\2"]){ ?>', $content);
}
//{if $value1!=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\!\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\!\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]!=$this->_var["\2"]){ ?>', $content);
}
//{if $value1===$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\=\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\=\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]===$this->_var["\2"]){ ?>', $content);
}
//{if $value1!==$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\!\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\!\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]!==$this->_var["\2"]){ ?>', $content);
}
//{if $value1!>$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\>\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\>\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]>$this->_var["\2"]){ ?>', $content);
}
//{if $value1!>=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\>\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\>\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]>=$this->_var["\2"]){ ?>', $content);
}
//{if $value1<$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\<\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\<\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]<$this->_var["\2"]){ ?>', $content);
}
//{if $value1<=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\<\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\<\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"]<=$this->_var["\2"]){ ?>', $content);
}
/*
if多条件判断
notice 多条件判断只支持普通变量, 不支持数组, 多条件判断目前最多支持两个条件, 不支持比较运算
*/
//&&运算
//{if $value1 and $value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\s+and\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\s+and\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"] && $this->_var["\2"]){ ?>', $content);
}
//{if !$value1 and !$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\s+and\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\s+and\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if(!$this->_var["\1"] && !$this->_var["\2"]){ ?>', $content);
}
//{if $value1 and !$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\s+and\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\s+and\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"] && !$this->_var["\2"]){ ?>', $content);
}
//{if !$value1 and $value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\s+and\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\s+and\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if(!$this->_var["\1"] && $this->_var["\2"]){ ?>', $content);
}
//||运算
//{if $value1 or $value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\s+or\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\$([a-zA-Z0-9_]+)\s+or\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"] || $this->_var["\2"]){ ?>', $content);
}
//{if !$value1 or !$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\s+or\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\s+or\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if(!$this->_var["\1"] || !$this->_var["\2"]){ ?>', $content);
}
//{if $value1 or !$value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\$[a-zA-Z0-9_]+\s+or\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '{if\s+\$([a-zA-Z0-9_]+)\s+or\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if($this->_var["\1"] || !$this->_var["\2"]){ ?>', $content);
}
//{if !$value1 or $value2}
if (preg_match('/\\' . $this->left_delimiter . 'if\s+\!\$[a-zA-Z0-9_]+\s+or\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'if\s+\!\$([a-zA-Z0-9_]+)\s+or\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php if(!$this->_var["\1"] || $this->_var["\2"]){ ?>', $content);
}
/* 解析{elseif标签} */
//{elseif $value}, $value为普通变量
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]){ ?>', $content);
}
//{elseif !$value}
if (preg_match('/\\' . $this->left_delimiter . '}elseif\s+\!\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\!\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php elseif(!$this->_var["\1"]){ ?>', $content);
}
//{elseif $value[key]}, 放入普通一维数组
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]["\2"]){ ?>', $content);
}
//{elseif !$value[key]}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\!\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\!\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php }elseif(!$this->_var["\1"]["\2"]){ ?>', $content);
}
/* 条件比较只支持普通变量比较, 如果要进行一维数组比较, 可在模板赋值时, 直接传入具体数组值 */
//{elseif $value1==$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]==$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1!=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\!\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\!\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]!=$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1===$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\=\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\=\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php elseif($this->_var["\1"]===$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1!==$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\!\=\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\!\=\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]!==$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1!>$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\>\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\>\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]>$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1!>=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\>\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\>\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]>=$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1<$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\<\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\<\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]<$this->_var["\2"]){ ?>', $content);
}
//{elseif $value1<=$value2}
if (preg_match('/\\' . $this->left_delimiter . 'elseif\s+\$[a-zA-Z0-9_]+\<\=\$[a-zA-Z0-9_]+\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . 'elseif\s+\$([a-zA-Z0-9_]+)\<\=\$([a-zA-Z0-9_]+)\\' . $this->right_delimiter . '/i', '<?php }elseif($this->_var["\1"]<=$this->_var["\2"]){ ?>', $content);
}
/* else标签解析 */
if (preg_match('/\{else\}/', $content, $res))
{
$content = preg_replace('/\{else\}/', '<?php }else{ ?>', $content);
}
//解析{/if}标签结束符
if (preg_match('/\\' . $this->left_delimiter . '\/if\\' . $this->right_delimiter . '/is', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '\/if\\' . $this->right_delimiter . '/', '<?php } ?>', $content);
}
//print_r($content);die;
return $content;
}
/*
普通一维数组变量 example: {$content[value]}
*/
protected function _array_var($content) {
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php echo $this->_var["\1"]["\2"]; ?>', $content);
return $content;
}
/*
cache标签: 可实现局部缓存
example: {cache}缓存内容{/cache}
*/
protected function _cache($content) {
if (preg_match_all('/\{cache\}(.*)?\{\/cache\}/iU', $content, $res))
{
$cache = '';
foreach ($res[1] as $v)
{
$cache .= $this->_eval($v);
}
}
return preg_replace('/\{cache\}.*?\{\/cache\}/i', $cache, $content);
}
/*
session标签
example: {$_SESSION[key]}
*/
protected function _session($content) {
return preg_replace('/\\' . $this->left_delimiter . '\$_SESSION\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php echo $_SESSION["\1"]; ?>', $content);
}
/*
cookie标签
example: {$_COOKIE[key]}
*/
protected function _cookie($content) {
return preg_replace('/\\' . $this->left_delimiter . '\$_COOKIE\[([a-zA-Z0-9_]+)\]\\' . $this->right_delimiter . '/i', '<?php echo $_COOKIE["\1"]; ?>', $content);
}
/*
captcha验证码标签
example: {captcha /} or {captcha type=img /}
notice: 为了保证静态页面也能使用, 这里采用绝对路径, 可换成域名
*/
protected function _captcha($content) {
if (preg_match('/\{captcha\s+\/\}/i', $content, $res))
{
$content = preg_replace('/\{captcha\s+\/\}/i', '<img src="lib_captcha.php" onclick=this.src="lib_captcha.php?"+Math.random(); style="cursor:pointer"/>', $content);
}
if (preg_match('/\{captcha\s+type\=img\s+\/\}/i', $content, $res))
{
$content = preg_replace('/\{captcha\s+type\=img\s+\/\}/i', '<img src="lib_captcha.php?type=img" onclick=this.src="lib_captcha.php?type=img&"+Math.random(); style="cursor:pointer"/>', $content);
}
return $content;
}
/*
*****************************************
*****************************************
系统函数标签
*****************************************
*****************************************
*/
/*
substr标签, 字符串截取
example: {$value: _substr(1,2)}
*/
protected function _substr($content) {
//普通变量截取
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\:\s+_substr\([0-9]+\,\s{0,}[0-9]+\)\\' . $this->right_delimiter . '/i', $content, $res))
{
if ($this->tpl_char == 'utf-8')
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\:\s+_substr\(([0-9]+)\,\s{0,}([0-9]+)\)\\' . $this->right_delimiter . '/i', '<?php echo substr($this->_var["\1"],\2,\3*3) . "..."; ?>', $content);
}
else
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\:\s+_substr\(([0-9]+)\,\s{0,}([0-9]+)\)\\' . $this->right_delimiter . '/i', '<?php echo substr($this->_var["\1"],\2,\3*2) . "..."; ?>', $content);
}
}
//foreach中数组变量截取
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+\:\s+_substr\([0-9]+\,\s{0,}[0-9]+\)\\' . $this->right_delimiter . '/i', $content, $res))
{
if ($this->tpl_char == 'utf-8')
{
$content = preg_replace('/\\' . $this->left_delimiter . '(\$[a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)\:\s+_substr\(([0-9]+)\,\s{0,}([0-9]+)\)\\' . $this->right_delimiter . '/i', '<?php echo substr(\1["\2"],\3,\4*3) . "..."; ?>', $content);
}
else
{
$content = preg_replace('/\\' . $this->left_delimiter . '(\$[a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)\:\s+_substr\(([0-9]+)\,\s{0,}([0-9]+)\)\\' . $this->right_delimiter . '/i', '<?php echo substr(\1["\2"],\3,\4*2) . "..."; ?>', $content);
}
}
//一维数组变量截取
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\:\s+_substr\([0-9]+\,\s{0,}[0-9]+\)\\' . $this->right_delimiter . '/i', $content, $res))
{
if ($this->tpl_char == 'utf-8')
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\:\s+_substr\(([0-9]+)\,\s{0,}([0-9]+)\)\\' . $this->right_delimiter . '/i', '<?php echo substr($this->_var["\1"]["\2"],\3,\4*3) . "..."; ?>', $content);
}
else
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\:\s+_substr\([0-9]+\,\s{0,}[0-9]+\)\\' . $this->right_delimiter . '/i', '<?php echo substr($this->_var["\1"]["\2"],\3,\4*2) . "..."; ?>', $content);
}
}
return $content;
}
/*
ucfirst, strtolower, strtoupper标签, 字符串首字母大写
example: {$value: _ucfirst()}
*/
protected function english_str($content, $type = 'ucfirst') {
//普通变量
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\:\s+_ucfirst\(\)\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\:\s+_' . $type . '\(\)\\' . $this->right_delimiter . '/i', '<?php echo ' . $type . '($this->_var["\1"]); ?>', $content);
}
//foreach中数组变量
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\.[a-zA-Z0-9_]+\:\s+_' . $type . '\(\)\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '(\$[a-zA-Z0-9_]+)\.([a-zA-Z0-9_]+)\:\s+_' . $type . '\(\)\\' . $this->right_delimiter . '/i', '<?php echo ' . $type . '(\1["\2"]); ?>', $content);
}
//普通一维数组
if (preg_match('/\\' . $this->left_delimiter . '\$[a-zA-Z0-9_]+\[[a-zA-Z0-9_]+\]\:\s+_' . $type . '\(\)\\' . $this->right_delimiter . '/i', $content, $res))
{
$content = preg_replace('/\\' . $this->left_delimiter . '\$([a-zA-Z0-9_]+)\[([a-zA-Z0-9_]+)\]\:\s+_' . $type . '\(\)\\' . $this->right_delimiter . '/i', '<?php echo ' . $type . '($this->_var["\1"]["\2"]); ?>', $content);
}
return $content;
}
/*
date:当前日期格式化函数标签
example: {_date()}
*/
protected function _date($content) {
return preg_replace('/\\' . $this->left_delimiter . '_date\(\)\\' . $this->right_delimiter . '/i', '<?php echo date("Y-m-d H:i:s"); ?>', $content);
}
/*
********************************
********************************
模板插件函数调用功能
********************************
********************************
*/
protected function _function($content) {
include ($this->tpl_plugins_file);
return preg_replace('/\\' . $this->left_delimiter . 'function\:\s+([a-zA-Z0-9]+\(\))\\' . $this->right_delimiter . '/i', '<?php function_\1; ?>', $content);
}
/*
********************************
********************************
自定义扩展标签
********************************
********************************
*/
protected function _extends($content) {
include ($this->tag_extends_file);
return preg_replace('/\\' . $this->left_delimiter . '(extends\:\s+([a-zA-Z0-9]+))\\' . $this->right_delimiter . '.*?\\' . $this->left_delimiter . '(\/extends\:\s+[a-zA-Z0-9]+)\\' . $this->right_delimiter . '/i', '<?php extends_\2("\1","\3"); ?>', $content);
}
/*
*********************************
*********************************
缓存控制
*********************************
*********************************
*/
/*
清除某个页面的静态文件
*/
function clear_static_cache($file) {
return @unlink($this->cache_dir . $file . $this->tpl_suffix);
}
/*
清除编译缓存文件
*/
function clear_make_cache($file) {
$make_name = $this->cpl_prefix . md5($this->compile_dir . $file) . '.php';
$make = $this->compile_dir . $make_name;
return @unlink($make);
}
/*
清除所有缓存
@type static 默认清除静态文件
make 清除编译文件
*/
function clear_all_cache($type = 'static') {
if ($type == 'static')
$dir = $this->cache_dir;
elseif ($type == 'make')
$dir = $this->compile_dir;
if (is_dir($dir))
{
$d = opendir($dir);
$filename = array();
while(($file = readdir($d)) !== false)
{
if ($file != '.' && $file != '..')
{
$filename[] = $file;
}
}
}
foreach ($filename as $f)
{
if ($type == 'static')
@unlink($this->cache_dir . $f);
elseif ($type == 'make')
@unlink($this->compile_dir . $f);
}
return true;
}
/*
************************************
************************************
模板表单安全处理
************************************
************************************
*/
/*
表单随机码生成, 防止跨域提交
*/
protected function _hash($content) {
if (preg_match('/<form.*?>.*?<\/form>/', $content, $form))
{
preg_match_all('/(<form.*?>)(.*?)<\/form>/', $content, $form);
$str = array();
foreach ($form[1] as $k => $f)
{
$str[] = $f . $form[2][$k] . '<input type="hidden" value="<?php echo $this->form_hash; ?>"></form>';
}
foreach ($form[0] as $k => $f)
{
$content = str_replace($f, $str[$k], $content);
}
$_SESSION['__HASH__'] = $this->form_hash;
return $content;
}
return $content;
}
}
?>