mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-01 20:52:48 +08:00
改进了标签替换方式,不需要递归进用替换,效率提升,也不用再限制标签嵌套层数。
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:
File diff suppressed because it is too large
Load Diff
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user