Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

View File

@ -0,0 +1,334 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\template;
use think\Exception;
/**
* ThinkPHP标签库TagLib解析基类
* @category Think
* @package Think
* @subpackage Template
* @author liu21st <liu21st@gmail.com>
*/
class TagLib
{
/**
* 标签库定义XML文件
* @var string
* @access protected
*/
protected $xml = '';
protected $tags = []; // 标签定义
/**
* 标签库名称
* @var string
* @access protected
*/
protected $tagLib = '';
/**
* 标签库标签列表
* @var array
* @access protected
*/
protected $tagList = [];
/**
* 标签库分析数组
* @var array
* @access protected
*/
protected $parse = [];
/**
* 标签库是否有效
* @var bool
* @access protected
*/
protected $valid = false;
/**
* 当前模板对象
* @var object
* @access protected
*/
protected $tpl;
protected $comparison = [' nheq ' => ' !== ', ' heq ' => ' === ', ' neq ' => ' != ', ' eq ' => ' == ', ' egt ' => ' >= ', ' gt ' => ' > ', ' elt ' => ' <= ', ' lt ' => ' < '];
/**
* 构造函数
* @access public
* @param \stdClass $template 模板引擎对象
*/
public function __construct($template)
{
$this->tpl = $template;
}
/**
* 按签标库替换页面中的标签
* @access public
* @param string $content 模板内容
* @param string $lib 标签库名
* @return void
*/
public function parseTag(&$content, $lib = '')
{
$tags = [];
$lib = $lib ? strtolower($lib) . ':' : '';
foreach ($this->tags as $name => $val) {
$close = !isset($val['close']) || $val['close'] ? 1 : 0;
$tags[$close][$lib . $name] = $name;
if (isset($val['alias'])) {
// 别名设置
$array = (array) $val['alias'];
foreach (explode(',', $array[0]) as $v) {
$tags[$close][$lib . $v] = $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 = strtolower($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 {
// 标签头压入栈
$right[strtolower($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']];
$alias = $lib . $name != $node['name'] ? ($lib ? strstr($node['name'], $lib) : $node['name']) : '';
// 解析标签属性
$attrs = $this->parseAttr($node['begin'][0], $name, $alias);
$method = 'tag' . $name;
// 读取标签库中对应的标签内容 replace[0]用来替换标签头replace[1]用来替换标签尾
$replace = explode($break, $this->$method($attrs, $break));
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);
$content = preg_replace_callback($regex, function ($matches) use (&$tags, &$lib) {
// 对应的标签名
$name = $tags[0][strtolower($matches[1])];
$alias = $lib . $name != $matches[1] ? ($lib ? strstr($matches[1], $lib) : $matches[1]) : '';
// 解析标签属性
$attrs = $this->parseAttr($matches[0], $name, $alias);
$method = 'tag' . $name;
return $this->$method($attrs, '');
}, $content);
}
return;
}
/**
* 按标签生成正则
* @access private
* @param array|string $tags 标签名
* @param boolean $close 是否为闭合标签
* @return string
*/
public 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;
$tagName = is_array($tags) ? implode('|', $tags) : $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';
}
/**
* 分析标签属性 正则方式
* @access public
* @param string $str 标签属性字符串
* @param string $name 标签名
* @param string $alias 别名
* @return array
*/
public function parseAttr($str, $name, $alias = '')
{
$regex = '/\s+(?>(?P<name>[\w-]+)\s*)=(?>\s*)([\"\'])(?P<value>(?:(?!\\2).)*)\\2/is';
$result = [];
if (preg_match_all($regex, $str, $matches)) {
foreach ($matches['name'] as $key => $val) {
$result[$val] = $matches['value'][$key];
}
if (!isset($this->tags[$name])) {
// 检测是否存在别名定义
foreach ($this->tags as $key => $val) {
if (isset($val['alias'])) {
$array = (array) $val['alias'];
if (in_array($name, explode(',', $array[0]))) {
$tag = $val;
$type = !empty($array[1]) ? $array[1] : 'type';
$result[$type] = $name;
break;
}
}
}
} else {
$tag = $this->tags[$name];
// 设置了标签别名
if (!empty($alias) && isset($tag['alias'])) {
$type = !empty($tag['alias'][1]) ? $tag['alias'][1] : 'type';
$result[$type] = $alias;
}
}
if (!empty($tag['must'])) {
$must = explode(',', $tag['must']);
foreach ($must as $name) {
if (!isset($result[$name])) {
throw new Exception('tag attr must:' . $name);
}
}
}
} else {
// 允许直接使用表达式的标签
if (!empty($this->tags[$name]['expression'])) {
static $_taglibs;
if (!isset($_taglibs[$name])) {
$_taglibs[$name][0] = strlen(ltrim($this->tpl->config('taglib_begin'), '\\') . $name);
$_taglibs[$name][1] = strlen(ltrim($this->tpl->config('taglib_end'), '\\'));
}
$result['expression'] = substr($str, $_taglibs[$name][0], -$_taglibs[$name][1]);
// 清除自闭合标签尾部/
$result['expression'] = rtrim($result['expression'], '/');
$result['expression'] = trim($result['expression']);
} elseif (empty($this->tags[$name]) || !empty($this->tags[$name]['attr'])) {
throw new Exception('tag error:' . $name);
}
}
return $result;
}
/**
* 解析条件表达式
* @access public
* @param string $condition 表达式标签内容
* @return string
*/
public function parseCondition($condition)
{
if (strpos($condition, ':')) {
$condition = ' ' . substr(strstr($condition, ':'), 1);
}
$condition = str_ireplace(array_keys($this->comparison), array_values($this->comparison), $condition);
$this->tpl->parseVar($condition);
// $this->tpl->parseVarFunction($condition); // XXX: 此句能解析表达式中用|分隔的函数,但表达式中如果有|、||这样的逻辑运算就产生了歧异
return $condition;
}
/**
* 自动识别构建变量
* @access public
* @param string $name 变量描述
* @return string
*/
public function autoBuildVar(&$name)
{
$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;
}
// 不以$开头并且也不是常量,自动补上$前缀
$name = '$' . $name;
}
$this->tpl->parseVar($name);
$this->tpl->parseVarFunction($name);
return $name;
}
/**
* 获取标签列表
* @access public
* @return array
*/
// 获取标签定义
public function getTags()
{
return $this->tags;
}
}

View File

@ -0,0 +1,71 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\template\driver;
use think\Exception;
class File
{
/**
* 写入编译缓存
* @param string $cacheFile 缓存的文件名
* @param string $content 缓存的内容
* @return void|array
*/
public function write($cacheFile, $content)
{
// 检测模板目录
$dir = dirname($cacheFile);
if (!is_dir($dir)) {
mkdir($dir, 0755, true);
}
// 生成模板缓存文件
if (false === file_put_contents($cacheFile, $content)) {
throw new Exception('cache write error:' . $cacheFile, 11602);
}
}
/**
* 读取编译编译
* @param string $cacheFile 缓存的文件名
* @param array $vars 变量数组
* @return void
*/
public function read($cacheFile, $vars = [])
{
if (!empty($vars) && is_array($vars)) {
// 模板阵列变量分解成为独立变量
extract($vars, EXTR_OVERWRITE);
}
//载入模版缓存文件
include $cacheFile;
}
/**
* 检查编译缓存是否有效
* @param string $cacheFile 缓存的文件名
* @param int $cacheTime 缓存时间
* @return boolean
*/
public function check($cacheFile, $cacheTime)
{
// 缓存文件不存在, 直接返回false
if (!file_exists($cacheFile)) {
return false;
}
if (0 != $cacheTime && $_SERVER['REQUEST_TIME'] > filemtime($cacheFile) + $cacheTime) {
// 缓存是否在有效期
return false;
}
return true;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,673 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think\template\taglib;
use think\template\TagLib;
/**
* CX标签库解析类
* @category Think
* @package Think
* @subpackage Driver.Taglib
* @author liu21st <liu21st@gmail.com>
*/
class Cx extends Taglib
{
// 标签定义
protected $tags = [
// 标签定义: attr 属性列表 close 是否闭合0 或者1 默认1 alias 标签别名 level 嵌套层次
'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, 'expression' => true],
'else' => ['attr' => '', 'close' => 0],
'switch' => ['attr' => 'name', 'expression' => true],
'case' => ['attr' => 'value,break', 'expression' => true],
'default' => ['attr' => '', 'close' => 0],
'compare' => ['attr' => 'name,value,type', 'alias' => ['eq,equal,notequal,neq,gt,lt,egt,elt,heq,nheq', 'type']],
'range' => ['attr' => 'name,value,type', 'alias' => ['in,notin,between,notbetween', 'type']],
'empty' => ['attr' => 'name'],
'notempty' => ['attr' => 'name'],
'present' => ['attr' => 'name'],
'notpresent' => ['attr' => 'name'],
'defined' => ['attr' => 'name'],
'notdefined' => ['attr' => 'name'],
'load' => ['attr' => 'file,href,type,value,basepath', 'close' => 0, 'alias' => ['import,css,js', 'type']],
'assign' => ['attr' => 'name,value', 'close' => 0],
'define' => ['attr' => 'name,value', 'close' => 0],
'for' => ['attr' => 'start,end,name,comparison,step'],
'url' => ['attr' => 'link,vars,suffix,domain', 'close' => 0, 'expression' => true],
'function' => ['attr' => 'name,vars,use,call'],
];
/**
* php标签解析
* 格式:
* {php}echo $name{/php}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagPhp($tag, $content)
{
$parseStr = '<?php ' . $content . ' ?>';
return $parseStr;
}
/**
* volist标签解析 循环输出数据集
* 格式:
* {volist name="userList" id="user" empty=""}
* {user.username}
* {user.email}
* {/volist}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string|void
*/
public function tagVolist($tag, $content)
{
$name = $tag['name'];
$id = $tag['id'];
$empty = isset($tag['empty']) ? $tag['empty'] : '';
$key = !empty($tag['key']) ? $tag['key'] : 'i';
$mod = isset($tag['mod']) ? $tag['mod'] : '2';
$offset = !empty($tag['offset']) && is_numeric($tag['offset']) ? intval($tag['offset']) : 0;
$length = !empty($tag['length']) && is_numeric($tag['length']) ? intval($tag['length']) : 'null';
// 允许使用函数设定数据集 <volist name=":fun('arg')" id="vo">{$vo.name}</volist>
$parseStr = '<?php ';
$flag = substr($name, 0, 1);
if (':' == $flag) {
$name = $this->autoBuildVar($name);
$parseStr .= '$_result=' . $name . ';';
$name = '$_result';
} else {
$name = $this->autoBuildVar($name);
}
$parseStr .= 'if(is_array(' . $name . ') || ' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator): $' . $key . ' = 0;';
// 设置了输出数组长度
if (0 != $offset || 'null' != $length) {
$parseStr .= '$__LIST__ = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
} else {
$parseStr .= ' $__LIST__ = ' . $name . ';';
}
$parseStr .= 'if( count($__LIST__)==0 ) : echo "' . $empty . '" ;';
$parseStr .= 'else: ';
$parseStr .= 'foreach($__LIST__ as $key=>$' . $id . '): ';
$parseStr .= '$mod = ($' . $key . ' % ' . $mod . ' );';
$parseStr .= '++$' . $key . ';?>';
$parseStr .= $content;
$parseStr .= '<?php endforeach; endif; else: echo "' . $empty . '" ;endif; ?>';
if (!empty($parseStr)) {
return $parseStr;
}
return;
}
/**
* foreach标签解析 循环输出数据集
* 格式:
* {foreach name="userList" id="user" key="key" index="i" mod="2" offset="3" length="5" empty=""}
* {user.username}
* {/foreach}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string|void
*/
public function tagForeach($tag, $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'];
$empty = isset($tag['empty']) ? $tag['empty'] : '';
$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 . ') || ' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator): ';
// 设置了输出数组长度
if (0 != $offset || 'null' != $length) {
if (!isset($var)) {
$var = '$_' . uniqid();
}
$parseStr .= $var . ' = is_array(' . $name . ') ? array_slice(' . $name . ',' . $offset . ',' . $length . ', true) : ' . $name . '->slice(' . $offset . ',' . $length . ', true); ';
} else {
$var = &$name;
}
$parseStr .= 'if( count(' . $var . ')==0 ) : echo "' . $empty . '" ;';
$parseStr .= 'else: ';
// 设置了索引项
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; else: echo "' . $empty . '" ;endif; ?>';
if (!empty($parseStr)) {
return $parseStr;
}
return;
}
/**
* if标签解析
* 格式:
* {if condition=" $a eq 1"}
* {elseif condition="$a eq 2" /}
* {else /}
* {/if}
* 表达式支持 eq neq gt egt lt elt == > >= < <= or and || &&
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagIf($tag, $content)
{
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
$parseStr = '<?php if(' . $condition . '): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* elseif标签解析
* 格式见if标签
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagElseif($tag, $content)
{
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
$parseStr = '<?php elseif(' . $condition . '): ?>';
return $parseStr;
}
/**
* else标签解析
* 格式见if标签
* @access public
* @param array $tag 标签属性
* @return string
*/
public function tagElse($tag)
{
$parseStr = '<?php else: ?>';
return $parseStr;
}
/**
* switch标签解析
* 格式:
* {switch name="a.name"}
* {case value="1" break="false"}1{/case}
* {case value="2" }2{/case}
* {default /}other
* {/switch}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagSwitch($tag, $content)
{
$name = !empty($tag['expression']) ? $tag['expression'] : $tag['name'];
$name = $this->autoBuildVar($name);
$parseStr = '<?php switch(' . $name . '): ?>' . $content . '<?php endswitch; ?>';
return $parseStr;
}
/**
* case标签解析 需要配合switch才有效
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagCase($tag, $content)
{
$value = !empty($tag['expression']) ? $tag['expression'] : $tag['value'];
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
$value = 'case ' . $value . ':';
} elseif (strpos($value, '|')) {
$values = explode('|', $value);
$value = '';
foreach ($values as $val) {
$value .= 'case "' . addslashes($val) . '":';
}
} else {
$value = 'case "' . $value . '":';
}
$parseStr = '<?php ' . $value . ' ?>' . $content;
$isBreak = isset($tag['break']) ? $tag['break'] : '';
if ('' == $isBreak || $isBreak) {
$parseStr .= '<?php break; ?>';
}
return $parseStr;
}
/**
* default标签解析 需要配合switch才有效
* 使用: {default /}ddfdf
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagDefault($tag)
{
$parseStr = '<?php default: ?>';
return $parseStr;
}
/**
* compare标签解析
* 用于值的比较 支持 eq neq gt lt egt elt heq nheq 默认是eq
* 格式: {compare name="" type="eq" value="" }content{/compare}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagCompare($tag, $content)
{
$name = $tag['name'];
$value = $tag['value'];
$type = isset($tag['type']) ? $tag['type'] : 'eq'; // 比较类型
$name = $this->autoBuildVar($name);
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
} else {
$value = '\'' . $value . '\'';
}
switch ($type) {
case 'equal':
$type = 'eq';
break;
case 'notequal':
$type = 'neq';
break;
}
$type = $this->parseCondition(' ' . $type . ' ');
$parseStr = '<?php if(' . $name . ' ' . $type . ' ' . $value . '): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* range标签解析
* 如果某个变量存在于某个范围 则输出内容 type= in 表示在范围内 否则表示在范围外
* 格式: {range name="var|function" value="val" type='in|notin' }content{/range}
* example: {range name="a" value="1,2,3" type='in' }content{/range}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagRange($tag, $content)
{
$name = $tag['name'];
$value = $tag['value'];
$type = isset($tag['type']) ? $tag['type'] : 'in'; // 比较类型
$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 . '"';
$str = 'explode(\',\',' . $value . ')';
}
if ('between' == $type) {
$parseStr = '<?php $_RANGE_VAR_=' . $str . ';if(' . $name . '>= $_RANGE_VAR_[0] && ' . $name . '<= $_RANGE_VAR_[1]):?>' . $content . '<?php endif; ?>';
} elseif ('notbetween' == $type) {
$parseStr = '<?php $_RANGE_VAR_=' . $str . ';if(' . $name . '<$_RANGE_VAR_[0] || ' . $name . '>$_RANGE_VAR_[1]):?>' . $content . '<?php endif; ?>';
} else {
$fun = ('in' == $type) ? 'in_array' : '!in_array';
$parseStr = '<?php if(' . $fun . '((' . $name . '), ' . $str . ')): ?>' . $content . '<?php endif; ?>';
}
return $parseStr;
}
/**
* present标签解析
* 如果某个变量已经设置 则输出内容
* 格式: {present name="" }content{/present}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagPresent($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
$parseStr = '<?php if(isset(' . $name . ')): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* notpresent标签解析
* 如果某个变量没有设置,则输出内容
* 格式: {notpresent name="" }content{/notpresent}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagNotpresent($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
$parseStr = '<?php if(!isset(' . $name . ')): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* empty标签解析
* 如果某个变量为empty 则输出内容
* 格式: {empty name="" }content{/empty}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagEmpty($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
$parseStr = '<?php if(empty(' . $name . ') || ((' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator ) && ' . $name . '->isEmpty())): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* notempty标签解析
* 如果某个变量不为empty 则输出内容
* 格式: {notempty name="" }content{/notempty}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagNotempty($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
$parseStr = '<?php if(!(empty(' . $name . ') || ((' . $name . ' instanceof \think\Collection || ' . $name . ' instanceof \think\Paginator ) && ' . $name . '->isEmpty()))): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* 判断是否已经定义了该常量
* {defined name='TXT'}已定义{/defined}
* @param array $tag
* @param string $content
* @return string
*/
public function tagDefined($tag, $content)
{
$name = $tag['name'];
$parseStr = '<?php if(defined("' . $name . '")): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* 判断是否没有定义了该常量
* {notdefined name='TXT'}已定义{/notdefined}
* @param array $tag
* @param string $content
* @return string
*/
public function tagNotdefined($tag, $content)
{
$name = $tag['name'];
$parseStr = '<?php if(!defined("' . $name . '")): ?>' . $content . '<?php endif; ?>';
return $parseStr;
}
/**
* load 标签解析 {load file="/static/js/base.js" /}
* 格式:{load file="/static/css/base.css" /}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagLoad($tag, $content)
{
$file = isset($tag['file']) ? $tag['file'] : $tag['href'];
$type = isset($tag['type']) ? strtolower($tag['type']) : '';
$parseStr = '';
$endStr = '';
// 判断是否存在加载条件 允许使用函数判断(默认为isset)
if (isset($tag['value'])) {
$name = $tag['value'];
$name = $this->autoBuildVar($name);
$name = 'isset(' . $name . ')';
$parseStr .= '<?php if(' . $name . '): ?>';
$endStr = '<?php endif; ?>';
}
// 文件方式导入
$array = explode(',', $file);
foreach ($array as $val) {
$type = strtolower(substr(strrchr($val, '.'), 1));
switch ($type) {
case 'js':
$parseStr .= '<script type="text/javascript" src="' . $val . '"></script>';
break;
case 'css':
$parseStr .= '<link rel="stylesheet" type="text/css" href="' . $val . '" />';
break;
case 'php':
$parseStr .= '<?php include "' . $val . '"; ?>';
break;
}
}
return $parseStr . $endStr;
}
/**
* assign标签解析
* 在模板中给某个变量赋值 支持变量赋值
* 格式: {assign name="" value="" /}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagAssign($tag, $content)
{
$name = $this->autoBuildVar($tag['name']);
$flag = substr($tag['value'], 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($tag['value']);
} else {
$value = '\'' . $tag['value'] . '\'';
}
$parseStr = '<?php ' . $name . ' = ' . $value . '; ?>';
return $parseStr;
}
/**
* define标签解析
* 在模板中定义常量 支持变量赋值
* 格式: {define name="" value="" /}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagDefine($tag, $content)
{
$name = '\'' . $tag['name'] . '\'';
$flag = substr($tag['value'], 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($tag['value']);
} else {
$value = '\'' . $tag['value'] . '\'';
}
$parseStr = '<?php define(' . $name . ', ' . $value . '); ?>';
return $parseStr;
}
/**
* for标签解析
* 格式:
* {for start="" end="" comparison="" step="" name=""}
* content
* {/for}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagFor($tag, $content)
{
//设置默认值
$start = 0;
$end = 0;
$step = 1;
$comparison = 'lt';
$name = 'i';
$rand = rand(); //添加随机数,防止嵌套变量冲突
//获取属性
foreach ($tag as $key => $value) {
$value = trim($value);
$flag = substr($value, 0, 1);
if ('$' == $flag || ':' == $flag) {
$value = $this->autoBuildVar($value);
}
switch ($key) {
case 'start':
$start = $value;
break;
case 'end':
$end = $value;
break;
case 'step':
$step = $value;
break;
case 'comparison':
$comparison = $value;
break;
case 'name':
$name = $value;
break;
}
}
$parseStr = '<?php $__FOR_START_' . $rand . '__=' . $start . ';$__FOR_END_' . $rand . '__=' . $end . ';';
$parseStr .= 'for($' . $name . '=$__FOR_START_' . $rand . '__;' . $this->parseCondition('$' . $name . ' ' . $comparison . ' $__FOR_END_' . $rand . '__') . ';$' . $name . '+=' . $step . '){ ?>';
$parseStr .= $content;
$parseStr .= '<?php } ?>';
return $parseStr;
}
/**
* url函数的tag标签
* 格式:{url link="模块/控制器/方法" vars="参数" suffix="true或者false 是否带有后缀" domain="true或者false 是否携带域名" /}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagUrl($tag, $content)
{
$url = isset($tag['link']) ? $tag['link'] : '';
$vars = isset($tag['vars']) ? $tag['vars'] : '';
$suffix = isset($tag['suffix']) ? $tag['suffix'] : 'true';
$domain = isset($tag['domain']) ? $tag['domain'] : 'false';
return '<?php echo url("' . $url . '","' . $vars . '",' . $suffix . ',' . $domain . ');?>';
}
/**
* function标签解析 匿名函数,可实现递归
* 使用:
* {function name="func" vars="$data" call="$list" use="&$a,&$b"}
* {if is_array($data)}
* {foreach $data as $val}
* {~func($val) /}
* {/foreach}
* {else /}
* {$data}
* {/if}
* {/function}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @return string
*/
public function tagFunction($tag, $content)
{
$name = !empty($tag['name']) ? $tag['name'] : 'func';
$vars = !empty($tag['vars']) ? $tag['vars'] : '';
$call = !empty($tag['call']) ? $tag['call'] : '';
$use = ['&$' . $name];
if (!empty($tag['use'])) {
foreach (explode(',', $tag['use']) as $val) {
$use[] = '&' . ltrim(trim($val), '&');
}
}
$parseStr = '<?php $' . $name . '=function(' . $vars . ') use(' . implode(',', $use) . ') {';
$parseStr .= ' ?>' . $content . '<?php }; ';
$parseStr .= $call ? '$' . $name . '(' . $call . '); ?>' : '?>';
return $parseStr;
}
}