改进了标签替换方式,不需要递归进用替换,效率提升,也不用再限制标签嵌套层数。

1. 兼容原来所有的标签功能和用法,已 对正则进行了优化,标签库和内置的普通标签可以使用一样的边界符,比如都用"{}",只要不重名不会相互干扰,这样这些标签就可以和html标签区分开。

 2. 模板支持多级继承。C继承B,而B又继承了A,C中的block会覆盖B和A中的同名block。

 3. include标签支持多层嵌套,可以传变量。如:
include file="Public/nav" selected="{$id}"
 在Public/nav模板用[selected]得到的是[$id}被解析后的值,而在3.2版中这样的写法是不能正确得到{$id}的值的。

 4. 增强了.语法的应用范围
 {$user.name.$group.name} 解析后是 <?php echo $user['name'].$group['name']; ?>
 {:substr($varname.aa, $varname.bb)} 解析后是 <?php echo substr($varname['aa'], $varname['bb']); ?>
 .语法在各个标签中都可以使用,$a.b.c这样的形式都能正确解析成$a['b']['c']

 5. 增加了一些新的语法
 {$varname.aa ?? 'xxx'} 表示如果有设置$varname则输出$varname,否则输出'xxx'。 解析后的代码为: <?php echo isset($varname['aa']) ? $varname['aa'] : '默认值'; ?>
 {$varname?='xxx'} 表示$varname为真时才输出xxx。 解析后的代码为: <?php if(!empty($name)) echo 'xxx'; ?>
 {$varname ?: 'no'} 表示如果$varname为真则输出$varname,否则输出no。解析后的代码为: <?php echo $varname ? $varname : 'no'; ?>
 {$a==$b ? 'yes' : 'no'} 前面的表达式为真输出yes,否则输出no, 条件可以是==、===、!=、!==、>=、<=

 6. 对if标签及foreach也加了一些更简洁的用法
{if condition="表达式"}
{if (表达式)}
{if 表达式}
这三种写法结果是一样的
{foreach $list as $v} 解析后是最简洁的,只一个foreach语句
{foreach name="list" item="v“} 这僦是原来的写法,解析后foreach外层会多一if判断,item换成id也可以
{foreach name="list" id="v" key="key" index="i" mod="2" offset="2" length="5"}
volist上的功能,foreach都有,只是volist默认会带上一些参数,而foreach需要指定这些参数才会生效
This commit is contained in:
yin
2015-12-24 00:41:48 +08:00
parent e9fadaebd1
commit e216563b09
3 changed files with 923 additions and 655 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -67,18 +67,163 @@ class TagLib
protected $comparison = [' nheq ' => ' !== ', ' heq ' => ' === ', ' neq ' => ' != ', ' eq ' => ' == ', ' egt ' => ' >= ', ' gt ' => ' > ', ' elt ' => ' <= ', ' lt ' => ' < '];
/**
* 架构函数
* @access public
* @param class $template 模板引擎对象
*/
public function __construct($template)
{
$this->tpl = $template;
}
/**
* 按签标库替换页面中的标签
* @access public
* @param string $content 模板内容
* @param string $lib 标签库名
* @return void
*/
public function parseTag(&$content, $lib = '')
{
$lib = strtolower($lib);
$tags = [];
foreach ($this->tags as $name => $val) {
$close = !isset($val['close']) || $val['close'] ? 1 : 0;
$_key = $lib ? $lib . ':' . $name : $name;
$tags[$close][$_key] = $name;
if (isset($val['alias'])) {
// 别名设置
foreach (explode(',', $val['alias']) as $v) {
$_key = $lib ? $lib . ':' . $v : $v;
$tags[$close][$_key] = $name;
}
}
}
// 闭合标签
if (!empty($tags[1])) {
$nodes = [];
$regex = $this->getRegex(array_keys($tags[1]), 1);
if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) {
$right = [];
foreach ($matches as $match) {
if ($match[1][0] == '') {
$name = $match[2][0];
// 如果有没闭合的标签头则取出最后一个
if (!empty($right[$name])) {
// $match[0][1]为标签结束符在模板中的位置
$nodes[$match[0][1]] = [
'name' => $name,
'begin' => array_pop($right[$name]), // 标签开始符
'end' => $match[0] // 标签结束符
];
} else {
continue;
}
} else {
// 标签头压入栈
$right[$match[1][0]][] = $match[0];
}
}
unset($right, $matches);
// 按标签在模板中的位置从后向前排序
krsort($nodes);
}
$break = '<!--###break###--!>';
if ($nodes) {
$beginArray = [];
// 标签替换 从后向前
foreach ($nodes as $pos => $node) {
// 对应的标签名
$name = $tags[1][$node['name']];
// 解析标签属性
$attrs = $this->parseAttr($node['begin'][0], $name);
$method = '_' . $name;
// 读取标签库中对应的标签内容 replace[0]用来替换标签头replace[1]用来替换标签尾
$replace = explode($break, $this->$method($attrs, $break, $node['name']));
if (count($replace) > 1) {
while ($beginArray) {
$begin = end($beginArray);
// 判断当前标签尾的位置是否在栈中最后一个标签头的后面,是则为子标签
if ($node['end'][1] > $begin['pos']) {
break;
} else {
// 不为子标签时,取出栈中最后一个标签头
$begin = array_pop($beginArray);
// 替换标签头部
$content = substr_replace($content, $begin['str'], $begin['pos'], $begin['len']);
}
}
// 替换标签尾部
$content = substr_replace($content, $replace[1], $node['end'][1], strlen($node['end'][0]));
// 把标签头压入栈
$beginArray[] = ['pos' => $node['begin'][1], 'len' => strlen($node['begin'][0]), 'str' => $replace[0]];
}
}
while ($beginArray) {
$begin = array_pop($beginArray);
// 替换标签头部
$content = substr_replace($content, $begin['str'], $begin['pos'], $begin['len']);
}
}
}
// 自闭合标签
if (!empty($tags[0])) {
$regex = $this->getRegex(array_keys($tags[0]), 0);
$self = &$this;
$content = preg_replace_callback($regex, function ($matches) use (&$tags, &$self) {
$name = $tags[0][$matches[1]];
// 解析标签属性
$attrs = $self->parseAttr($matches[0], $name);
$method = '_' . $name;
return $self->$method($attrs, '', $matches[1]);
}, $content);
}
return;
}
/**
* 按标签生成正则
* @access private
* @param array|string $tags 标签名
* @param boolean $close 是否为闭合标签
* @return string
*/
private function getRegex($tags, $close)
{
$begin = $this->tpl->config['taglib_begin'];
$end = $this->tpl->config['taglib_end'];
$single = strlen(ltrim($begin, '\\')) == 1 && strlen(ltrim($end, '\\')) == 1 ? true : false;
if (is_array($tags)) {
$tagName = implode('|', $tags);
} else {
$tagName = $tags;
}
if ($single) {
if ($close) {
// 如果是闭合标签
$regex = $begin . '(?:(' . $tagName . ')\b(?>[^' . $end . ']*)|\/(' . $tagName . '))' . $end;
} else {
$regex = $begin . '(' . $tagName . ')\b(?>[^' . $end . ']*)' . $end;
}
} else {
if ($close) {
// 如果是闭合标签
$regex = $begin . '(?:(' . $tagName . ')\b(?>(?:(?!' . $end . ').)*)|\/(' . $tagName . '))' . $end;
} else {
$regex = $begin . '(' . $tagName . ')\b(?>(?:(?!' . $end . ').)*)' . $end;
}
}
return '/' . $regex . '/is';
}
/**
* TagLib标签属性分析 返回标签属性数组
* @access public
*
* @param $attr
* @param $tag
*
* @access public
* @param string $attr 标签属性字符串
* @param string $tag 标签名
* @return array
* @throws Exception
* @internal param string $tagStr 标签内容
@@ -90,53 +235,116 @@ class TagLib
}
//XML解析安全过滤
$attr = str_replace('&', '___', $attr);
$xml = '<tpl><tag ' . $attr . ' /></tpl>';
$xml = simplexml_load_string($xml);
if (substr($attr, 0, 1) == '<' && substr($attr, -1, 1) == '>') {
$xml = '<tpl>' . $attr . '</tpl>';
} else {
$xml = '<tpl><tag ' . $attr . ' /></tpl>';
}
$xml = simplexml_load_string($xml);
if (!$xml) {
throw new Exception('_XML_TAG_ERROR_ : ' . $attr);
}
$xml = (array) ($xml->tag->attributes());
$array = array_change_key_case($xml['@attributes']);
if (!is_array($array)) {
return [];
}
$tag = strtolower($tag);
if (isset($this->tags[$tag]['attr'])) {
$attrs = explode(',', $this->tags[$tag]['attr']);
if (isset($this->tags[strtolower($tag)]['must'])) {
$must = explode(',', $this->tags[$tag]['must']);
$xml = (array)($xml->tag->attributes());
if (isset($xml['@attributes']) && $result = array_change_key_case($xml['@attributes'])) {
$tag = strtolower($tag);
if (!isset($this->tags[$tag])) {
// 检测是否存在别名定义
foreach ($this->tags as $key => $val) {
if (isset($val['alias']) && in_array($tag, explode(',', $val['alias']))) {
$item = $val;
break;
}
}
} else {
$must = [];
$item = $this->tags[$tag];
}
foreach ($attrs as $name) {
if (isset($array[$name])) {
$array[$name] = str_replace('___', '&', $array[$name]);
} elseif (false !== array_search($name, $must)) {
throw new Exception('_PARAM_ERROR_:' . $name);
if (!empty($item['attr'])) {
if (isset($item['must'])) {
$must = explode(',', $item['must']);
} else {
$must = [];
}
$attrs = explode(',', $item['attr']);
foreach ($attrs as $name) {
if (isset($result[$name])) {
$result[$name] = str_replace('___', '&', $result[$name]);
} elseif (false !== array_search($name, $must)) {
throw new Exception('_PARAM_ERROR_:' . $name);
}
}
}
return $result;
} else {
return [];
}
}
return $array;
/**
* 分析标签属性 正则方式
* @access public
* @param string $str 标签属性字符串
* @param string $tag 标签名
* @return array
*/
public function parseAttr($str, $tag)
{
if (ini_get('magic_quotes_sybase')) {
$str = str_replace('\"', '\'', $str);
}
$regex = '/\s+(?>(?<name>\w+)\s*)=(?>\s*)([\"\'])(?<value>(?:(?!\\2).)*)\\2/is';
$result = [];
if (preg_match_all($regex, $str, $matches)) {
foreach ($matches['name'] as $key => $val) {
$result[$val] = $matches['value'][$key];
}
$tag = strtolower($tag);
if (!isset($this->tags[$tag])) {
// 检测是否存在别名定义
foreach ($this->tags as $key => $val) {
if (isset($val['alias']) && in_array($tag, explode(',', $val['alias']))) {
$item = $val;
break;
}
}
} else {
$item = $this->tags[$tag];
}
if (!empty($item['must'])) {
$must = explode(',', $item['must']);
foreach ($must as $name) {
if (!isset($result[$name])) {
throw new Exception('_PARAM_ERROR_:' . $name);
}
}
}
} else {
// 允许直接使用表达式的标签
if (!empty($this->tags[$tag]['expression'])) {
static $_taglibs;
if (!isset($_taglibs[$tag])) {
$_taglibs[$tag][0] = strlen($this->tpl->config['taglib_begin'] . $tag);
$_taglibs[$tag][1] = strlen($this->tpl->config['taglib_end']);
}
$str = substr($str, $_taglibs[$tag][0], -$_taglibs[$tag][1]);
$result['expression'] = trim($str);
} elseif (empty($this->tags[$tag]) || !empty($this->tags[$tag]['attr'])) {
throw new Exception('_XML_TAG_ERROR_:' . $tag);
}
}
return $result;
}
/**
* 解析条件表达式
* @access public
* @param string $condition 表达式标签内容
* @return array
* @param string $condition 表达式标签内容
* @return string
*/
public function parseCondition($condition)
{
$condition = str_ireplace(array_keys($this->comparison), array_values($this->comparison), $condition);
$condition = preg_replace('/\$(\w+):(\w+)\s/is', '$\\1->\\2 ', $condition);
$condition = preg_replace('/\$(\w+)\.(\w+)\s/is', '$\\1["\\2"] ', $condition);
if (false !== strpos($condition, '$Think')) {
$condition = preg_replace('/(\$Think.*?)\s/ies', "\$this->parseThinkVar('\\1');", $condition);
}
$this->tpl->parseVar($condition);
$this->tpl->parseVarFunction($condition); // XXX: 此句能解析表达式中用|分隔的函数,但表达式中如果有|、||这样的逻辑运算就产生了歧异
return $condition;
}
@@ -146,133 +354,30 @@ class TagLib
* @param string $name 变量描述
* @return string
*/
public function autoBuildVar($name)
public function autoBuildVar(&$name)
{
if ('Think.' == substr($name, 0, 6)) {
// 特殊变量
return $this->parseThinkVar($name);
} elseif (strpos($name, '.')) {
$vars = explode('.', $name);
$var = array_shift($vars);
$name = '$' . $var;
foreach ($vars as $key => $val) {
if (0 === strpos($val, '$')) {
$name .= '["{' . $val . '}"]';
} else {
$name .= '["' . $val . '"]';
}
$flag = substr($name, 0, 1);
if (':' == $flag) {
// 以:开头为函数调用,解析前去掉:
$name = substr($name, 1);
} elseif ('$' != $flag && preg_match('/[a-zA-Z_]/', $flag)) { // XXX: 这句的写法可能还需要改进
// 常量不需要解析
if (defined($name)) {
return $name;
}
} elseif (strpos($name, ':')) {
// 额外的对象方式支持
$name = '$' . str_replace(':', '->', $name);
} elseif (!defined($name)) {
// 不以$开头并且也不是常量,自动补上$前缀
$name = '$' . $name;
}
$this->tpl->parseVar($name);
$this->tpl->parseVarFunction($name);
return $name;
}
/**
* 用于标签属性里面的特殊模板变量解析
* 格式 以 Think. 打头的变量属于特殊模板变量
* 获取标签列表
* @access public
* @param string $varStr 变量字符串
* @return string
* @return array
*/
public function parseThinkVar($varStr)
{
$vars = explode('.', $varStr);
$vars[1] = strtoupper(trim($vars[1]));
$parseStr = '';
if (count($vars) >= 3) {
$vars[2] = trim($vars[2]);
switch ($vars[1]) {
case 'SERVER':$parseStr = '$_SERVER[\'' . $vars[2] . '\']';
break;
case 'GET':$parseStr = '$_GET[\'' . $vars[2] . '\']';
break;
case 'POST':$parseStr = '$_POST[\'' . $vars[2] . '\']';
break;
case 'COOKIE':
if (isset($vars[3])) {
$parseStr = '$_COOKIE[\'' . $vars[2] . '\'][\'' . $vars[3] . '\']';
} else {
$parseStr = '\\think\\cookie::get(\'' . $vars[2] . '\')';
}
break;
case 'SESSION':
if (isset($vars[3])) {
$parseStr = '$_SESSION[\'' . $vars[2] . '\'][\'' . $vars[3] . '\']';
} else {
$parseStr = '\\think\\session::get(\'' . $vars[2] . '\')';
}
break;
case 'ENV':$parseStr = '$_ENV[\'' . $vars[2] . '\']';
break;
case 'REQUEST':$parseStr = '$_REQUEST[\'' . $vars[2] . '\']';
break;
case 'CONST':$parseStr = strtoupper($vars[2]);
break;
case 'LANG':
$parseStr = '\\think\\Lang::get("' . $vars[2] . '")';
break;
case 'CONFIG':
if (isset($vars[3])) {
$vars[2] .= '.' . $vars[3];
}
$parseStr = '\\think\\config::get("' . $vars[2] . '")';
break;
}
} else if (count($vars) == 2) {
switch ($vars[1]) {
case 'NOW':$parseStr = "date('Y-m-d g:i a',time())";
break;
case 'VERSION':$parseStr = 'THINK_VERSION';
break;
default:if (defined($vars[1])) {
$parseStr = $vars[1];
}
}
}
return $parseStr;
}
/**
* 对模板变量使用函数
* 格式 {$varname|function1|function2=arg1,arg2}
* @access protected
* @param string $name 变量名
* @param array $varArray 函数列表
* @return string
*/
protected function parseVarFunction($name, $varArray)
{
//对变量使用函数
$length = count($varArray);
for ($i = 0; $i < $length; $i++) {
$args = explode('=', $varArray[$i], 2);
//模板函数过滤
$fun = strtolower(trim($args[0]));
switch ($fun) {
case 'default': // 特殊模板函数
$name = '(' . $name . ')?(' . $name . '):' . $args[1];
break;
default: // 通用模板函数
if (isset($args[1])) {
if (strstr($args[1], '###')) {
$args[1] = str_replace('###', $name, $args[1]);
$name = "$fun($args[1])";
} else {
$name = "$fun($name,$args[1])";
}
} else if (!empty($args[0])) {
$name = "$fun($name)";
}
}
}
return $name;
}
// 获取标签定义
public function getTags()
{

View File

@@ -2,7 +2,7 @@
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2012 http://thinkphp.cn All rights reserved.
// | Copyright (c) 2006-2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
@@ -26,34 +26,34 @@ class Cx extends Taglib
// 标签定义
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'php' => [],
'volist' => ['attr' => 'name,id,offset,length,key,mod', 'level' => 3, 'alias' => 'iterate'],
'foreach' => ['attr' => 'name,item,key', 'level' => 3],
'if' => ['attr' => 'condition', 'level' => 2],
'php' => ['attr' => ''],
'volist' => ['attr' => 'name,id,offset,length,key,mod', 'alias' => 'iterate'],
'foreach' => ['attr' => 'name,id,item,key,offset,length,mod', 'expression' => true],
'if' => ['attr' => 'condition', 'expression' => true],
'elseif' => ['attr' => 'condition', 'close' => 0],
'else' => ['attr' => '', 'close' => 0],
'switch' => ['attr' => 'name', 'level' => 2],
'case' => ['attr' => 'value,break', 'level' => 2],
'switch' => ['attr' => 'name'],
'case' => ['attr' => 'value,break'],
'default' => ['attr' => '', 'close' => 0],
'compare' => ['attr' => 'name,value,type', 'level' => 3, 'alias' => 'eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq'],
'range' => ['attr' => 'name,value,type', 'level' => 3, 'alias' => 'in,notin,between,notbetween'],
'empty' => ['attr' => 'name', 'level' => 3],
'notempty' => ['attr' => 'name', 'level' => 3],
'present' => ['attr' => 'name', 'level' => 3],
'notpresent' => ['attr' => 'name', 'level' => 3],
'defined' => ['attr' => 'name', 'level' => 3],
'notdefined' => ['attr' => 'name', 'level' => 3],
'compare' => ['attr' => 'name,value,type', 'alias' => 'eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq'],
'range' => ['attr' => 'name,value,type', 'alias' => 'in,notin,between,notbetween'],
'empty' => ['attr' => 'name'],
'notempty' => ['attr' => 'name'],
'present' => ['attr' => 'name'],
'notpresent' => ['attr' => 'name'],
'defined' => ['attr' => 'name'],
'notdefined' => ['attr' => 'name'],
'import' => ['attr' => 'file,href,type,value,basepath', 'close' => 0, 'alias' => 'load,css,js'],
'assign' => ['attr' => 'name,value', 'close' => 0],
'define' => ['attr' => 'name,value', 'close' => 0],
'for' => ['attr' => 'start,end,name,comparison,step', 'level' => 3],
'for' => ['attr' => 'start,end,name,comparison,step'],
];
/**
* php标签解析
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _php($tag, $content)
@@ -71,7 +71,7 @@ class Cx extends Taglib
* </volist>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string|void
*/
public function _volist($tag, $content)
@@ -83,8 +83,10 @@ class Cx extends Taglib
$mod = isset($tag['mod']) ? $tag['mod'] : '2';
// 允许使用函数设定数据集 <volist name=":fun('arg')" id="vo">{$vo.name}</volist>
$parseStr = '<?php ';
if (0 === strpos($name, ':')) {
$parseStr .= '$_result=' . substr($name, 1) . ';';
$flag = substr($name, 0, 1);
if (':' == $flag) {
$name = $this->autoBuildVar($name);
$parseStr .= '$_result=' . $name . ';';
$name = '$_result';
} else {
$name = $this->autoBuildVar($name);
@@ -102,7 +104,7 @@ class Cx extends Taglib
$parseStr .= 'foreach($__LIST__ as $key=>$' . $id . '): ';
$parseStr .= '$mod = ($' . $key . ' % ' . $mod . ' );';
$parseStr .= '++$' . $key . ';?>';
$parseStr .= ($content);
$parseStr .= $content;
$parseStr .= '<?php endforeach; endif; else: echo "' . $empty . '" ;endif; ?>';
if (!empty($parseStr)) {
@@ -115,18 +117,70 @@ class Cx extends Taglib
* foreach标签解析 循环输出数据集
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string|void
*/
public function _foreach($tag, $content)
{
$name = $tag['name'];
$item = $tag['item'];
$key = !empty($tag['key']) ? $tag['key'] : 'key';
$name = $this->autoBuildVar($name);
$parseStr = '<?php if(is_array(' . $name . ')): foreach(' . $name . ' as $' . $key . '=>$' . $item . '): ?>';
$parseStr .= ($content);
// 直接使用表达式
if (!empty($tag['expression'])) {
$expression = ltrim(rtrim($tag['expression'], ')'), '(');
$expression = $this->autoBuildVar($expression);
$parseStr = '<?php foreach(' . $expression . '): ?>';
$parseStr .= $content;
$parseStr .= '<?php endforeach; ?>';
return $parseStr;
}
$name = $tag['name'];
$key = !empty($tag['key']) ? $tag['key'] : 'key';
$item = !empty($tag['id']) ? $tag['id'] : $tag['item'];
$offset = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0;
$length = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null';
$parseStr = '<?php ';
// 支持用函数传数组
if (':' == substr($name, 0, 1)) {
$var = '$_' . uniqid();
$name = $this->autoBuildVar($name);
$parseStr .= $var . '=' . $name . '; ';
$name = $var;
} else {
$name = $this->autoBuildVar($name);
}
$parseStr .= 'if(is_array(' . $name . ')): ';
// 设置了输出数组长度
if ($offset != 0 || $length != 'null') {
if (!isset($var)) {
$var = '$_' . uniqid();
}
$parseStr .= $var . ' = array_slice(' . $name . ',' . $offset . ',' . $length . ',true); ';
} else {
$var = &$name;
}
// 设置了索引项
if (isset($tag['index'])) {
$index = $tag['index'];
$parseStr .= '$' . $index . '=0; ';
}
$parseStr .= 'foreach(' . $var . ' as $' . $key . '=>$' . $item . '): ';
// 设置了索引项
if (isset($tag['index'])) {
$index = $tag['index'];
if (isset($tag['mod'])) {
$mod = (int)$tag['mod'];
$parseStr .= '$mod = ($' . $index . ' % ' . $mod . '); ';
}
$parseStr .= '++$' . $index . '; ';
}
$parseStr .= '?>';
// 循环体中的内容
$parseStr .= $content;
$parseStr .= '<?php endforeach; endif; ?>';
// 设置了数组为空时的显示内容
if (isset($tag['empty'])) {
$parseStr .= '<?php if(empty(' . $var . ')): echo \'"' . $tag['empty'] . '\'; endif; ?>';
}
if (!empty($parseStr)) {
return $parseStr;
}
@@ -143,12 +197,13 @@ class Cx extends Taglib
* 表达式支持 eq neq gt egt lt elt == > >= < <= or and || &&
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _if($tag, $content)
{
$condition = $this->parseCondition($tag['condition']);
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
$parseStr = '<?php if(' . $condition . '): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
@@ -158,12 +213,13 @@ class Cx extends Taglib
* 格式见if标签
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _elseif($tag, $content)
{
$condition = $this->parseCondition($tag['condition']);
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
$parseStr = '<?php elseif(' . $condition . '): ?>';
return $parseStr;
}
@@ -190,19 +246,13 @@ class Cx extends Taglib
* </switch>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _switch($tag, $content)
{
$name = $tag['name'];
$varArray = explode('|', $name);
$name = array_shift($varArray);
$name = $this->autoBuildVar($name);
if (count($varArray) > 0) {
$name = $this->parseVarFunction($name, $varArray);
}
$parseStr = '<?php switch(' . $name . '): ?>' . $content . '<?php endswitch;?>';
return $parseStr;
}
@@ -211,20 +261,15 @@ class Cx extends Taglib
* case标签解析 需要配合switch才有效
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _case($tag, $content)
{
$value = $tag['value'];
if ('$' == substr($value, 0, 1)) {
$varArray = explode('|', $value);
$value = array_shift($varArray);
$value = $this->autoBuildVar(substr($value, 1));
if (count($varArray) > 0) {
$value = $this->parseVarFunction($value, $varArray);
}
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
$value = 'case ' . $value . ': ';
} elseif (strpos($value, '|')) {
$values = explode('|', $value);
@@ -248,7 +293,7 @@ class Cx extends Taglib
* 使用: <default />ddfdf
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _default($tag)
@@ -263,27 +308,22 @@ class Cx extends Taglib
* 格式: <compare name="" type="eq" value="" >content</compare>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _compare($tag, $content, $type = 'eq')
{
$name = $tag['name'];
$value = $tag['value'];
$type = isset($tag['type']) ? $tag['type'] : $type;
$type = $this->parseCondition(' ' . $type . ' ');
$varArray = explode('|', $name);
$name = array_shift($varArray);
$name = $this->autoBuildVar($name);
if (count($varArray) > 0) {
$name = $this->parseVarFunction($name, $varArray);
}
if ('$' == substr($value, 0, 1)) {
$value = $this->autoBuildVar(substr($value, 1));
$name = $tag['name'];
$value = $tag['value'];
$type = isset($tag['type']) ? $tag['type'] : $type;
$name = $this->autoBuildVar($name);
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
} else {
$value = '"' . $value . '"';
$value = '\'' . $value . '\'';
}
$type = $this->parseCondition(' ' . $type . ' ');
$parseStr = '<?php if((' . $name . ') ' . $type . ' ' . $value . '): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
@@ -345,25 +385,20 @@ class Cx extends Taglib
* example: <range name="a" value="1,2,3" type='in' >content</range>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $type 比较类型
* @param string $content 标签内容
* @param string $type 比较类型
* @return string
*/
public function _range($tag, $content, $type = 'in')
{
$name = $tag['name'];
$value = $tag['value'];
$varArray = explode('|', $name);
$name = array_shift($varArray);
$name = $this->autoBuildVar($name);
if (count($varArray) > 0) {
$name = $this->parseVarFunction($name, $varArray);
}
$name = $tag['name'];
$value = $tag['value'];
$type = isset($tag['type']) ? $tag['type'] : $type;
$type = isset($tag['type']) ? $tag['type'] : $type;
if ('$' == substr($value, 0, 1)) {
$value = $this->autoBuildVar(substr($value, 1));
$name = $this->autoBuildVar($name);
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
$str = 'is_array(' . $value . ')?' . $value . ':explode(\',\',' . $value . ')';
} else {
$value = '"' . $value . '"';
@@ -408,7 +443,7 @@ class Cx extends Taglib
* 格式: <present name="" >content</present>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _present($tag, $content)
@@ -425,7 +460,7 @@ class Cx extends Taglib
* 格式: <notpresent name="" >content</notpresent>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _notpresent($tag, $content)
@@ -442,7 +477,7 @@ class Cx extends Taglib
* 格式: <empty name="" >content</empty>
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _empty($tag, $content)
@@ -464,8 +499,8 @@ class Cx extends Taglib
/**
* 判断是否已经定义了该常量
* <defined name='TXT'>已定义</defined>
* @param <type> $tag
* @param <type> $content
* @param array $tag
* @param string $content
* @return string
*/
public function _defined($tag, $content)
@@ -487,9 +522,9 @@ class Cx extends Taglib
* <import file="Css.Base" type="css" />
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param boolean $isFile 是否文件方式
* @param string $type 类型
* @param string $content 标签内容
* @param boolean $isFile 是否文件方式
* @param string $type 类型
* @return string
*/
public function _import($tag, $content, $isFile = false, $type = '')
@@ -499,15 +534,9 @@ class Cx extends Taglib
$endStr = '';
// 判断是否存在加载条件 允许使用函数判断(默认为isset)
if (isset($tag['value'])) {
$varArray = explode('|', $tag['value']);
$name = array_shift($varArray);
$name = $this->autoBuildVar($name);
if (!empty($varArray)) {
$name = $this->parseVarFunction($name, $varArray);
} else {
$name = 'isset(' . $name . ')';
}
$name = $tag['value'];
$name = $this->autoBuildVar($name);
$name = 'isset(' . $name . ')';
$parseStr .= '<?php if(' . $name . '): ?>';
$endStr = '<?php endif; ?>';
}
@@ -539,7 +568,11 @@ class Cx extends Taglib
// 命名空间方式导入外部文件
$array = explode(',', $file);
foreach ($array as $val) {
list($val, $version) = explode('?', $val);
if (strpos($val, '?')) {
list($val, $version) = explode('?', $val);
} else {
$version = '';
}
switch ($type) {
case 'js':
$parseStr .= '<script type="text/javascript" src="' . $basepath . '/' . str_replace(['.', '#'], ['/', '.'], $val) . '.js' . ($version ? '?' . $version : '') . '"></script>';
@@ -580,14 +613,15 @@ class Cx extends Taglib
* 格式: <assign name="" value="" />
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _assign($tag, $content)
{
$name = $this->autoBuildVar($tag['name']);
if ('$' == substr($tag['value'], 0, 1)) {
$value = $this->autoBuildVar(substr($tag['value'], 1));
$flag = substr($tag['value'], 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($tag['value']);
} else {
$value = '\'' . $tag['value'] . '\'';
}
@@ -601,14 +635,15 @@ class Cx extends Taglib
* 格式: <define name="" value="" />
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _define($tag, $content)
{
$name = '\'' . $tag['name'] . '\'';
if ('$' == substr($tag['value'], 0, 1)) {
$value = $this->autoBuildVar(substr($tag['value'], 1));
$flag = substr($tag['value'], 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($tag['value']);
} else {
$value = '\'' . $tag['value'] . '\'';
}
@@ -621,7 +656,7 @@ class Cx extends Taglib
* 格式: <for start="" end="" comparison="" step="" name="" />
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param string $content 标签内容
* @return string
*/
public function _for($tag, $content)
@@ -636,10 +671,9 @@ class Cx extends Taglib
//获取属性
foreach ($tag as $key => $value) {
$value = trim($value);
if (':' == substr($value, 0, 1)) {
$value = substr($value, 1);
} elseif ('$' == substr($value, 0, 1)) {
$value = $this->autoBuildVar(substr($value, 1));
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
}
switch ($key) {