$xml
$xml : string
标签库定义XML文件
ThinkPHP标签库TagLib解析基类
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Think\Template;
/**
* ThinkPHP标签库TagLib解析基类
*/
class TagLib
{
/**
* 标签库定义XML文件
* @var string
* @access protected
*/
protected $xml = '';
protected $tags = array(); // 标签定义
/**
* 标签库名称
* @var string
* @access protected
*/
protected $tagLib = '';
/**
* 标签库标签列表
* @var string
* @access protected
*/
protected $tagList = array();
/**
* 标签库分析数组
* @var string
* @access protected
*/
protected $parse = array();
/**
* 标签库是否有效
* @var string
* @access protected
*/
protected $valid = false;
/**
* 当前模板对象
* @var object
* @access protected
*/
protected $tpl;
protected $comparison = array(' nheq ' => ' !== ', ' heq ' => ' === ', ' neq ' => ' != ', ' eq ' => ' == ', ' egt ' => ' >= ', ' gt ' => ' > ', ' elt ' => ' <= ', ' lt ' => ' < ');
/**
* 架构函数
* @access public
*/
public function __construct()
{
$this->tagLib = strtolower(substr(get_class($this), 6));
$this->tpl = \Think\Think::instance('Think\\Template');
}
/**
* TagLib标签属性分析 返回标签属性数组
* @access public
* @param string $tagStr 标签内容
* @return array
*/
public function parseXmlAttr($attr, $tag)
{
//XML解析安全过滤
$attr = str_replace('&', '___', $attr);
$xml = '<tpl><tag ' . $attr . ' /></tpl>';
$xml = simplexml_load_string($xml);
if (!$xml) {
E(L('_XML_TAG_ERROR_') . ' : ' . $attr);
}
$xml = (array) ($xml->tag->attributes());
if (isset($xml['@attributes'])) {
$array = array_change_key_case($xml['@attributes']);
if ($array) {
$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];
}
$attrs = explode(',', $item['attr']);
if (isset($item['must'])) {
$must = explode(',', $item['must']);
} else {
$must = array();
}
foreach ($attrs as $name) {
if (isset($array[$name])) {
$array[$name] = str_replace('___', '&', $array[$name]);
} elseif (false !== array_search($name, $must)) {
E(L('_PARAM_ERROR_') . ':' . $name);
}
}
return $array;
}
} else {
return array();
}
}
/**
* 解析条件表达式
* @access public
* @param string $condition 表达式标签内容
* @return array
*/
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);
switch (strtolower(C('TMPL_VAR_IDENTIFY'))) {
case 'array': // 识别为数组
$condition = preg_replace('/\$(\w+)\.(\w+)\s/is', '$\\1["\\2"] ', $condition);
break;
case 'obj': // 识别为对象
$condition = preg_replace('/\$(\w+)\.(\w+)\s/is', '$\\1->\\2 ', $condition);
break;
default: // 自动判断数组或对象 只支持二维
$condition = preg_replace('/\$(\w+)\.(\w+)\s/is', '(is_array($\\1)?$\\1["\\2"]:$\\1->\\2) ', $condition);
}
if (false !== strpos($condition, '$Think')) {
$condition = preg_replace_callback('/(\$Think.*?)\s/is', array($this, 'parseThinkVar'), $condition);
}
return $condition;
}
/**
* 自动识别构建变量
* @access public
* @param string $name 变量描述
* @return string
*/
public function autoBuildVar($name)
{
if ('Think.' == substr($name, 0, 6)) {
// 特殊变量
return $this->parseThinkVar($name);
} elseif (strpos($name, '.')) {
$vars = explode('.', $name);
$var = array_shift($vars);
switch (strtolower(C('TMPL_VAR_IDENTIFY'))) {
case 'array': // 识别为数组
$name = '$' . $var;
foreach ($vars as $key => $val) {
if (0 === strpos($val, '$')) {
$name .= '["{' . $val . '}"]';
} else {
$name .= '["' . $val . '"]';
}
}
break;
case 'obj': // 识别为对象
$name = '$' . $var;
foreach ($vars as $key => $val) {
$name .= '->' . $val;
}
break;
default: // 自动判断数组或对象 只支持二维
$name = 'is_array($' . $var . ')?$' . $var . '["' . $vars[0] . '"]:$' . $var . '->' . $vars[0];
}
} elseif (strpos($name, ':')) {
// 额外的对象方式支持
$name = '$' . str_replace(':', '->', $name);
} elseif (!defined($name)) {
$name = '$' . $name;
}
return $name;
}
/**
* 用于标签属性里面的特殊模板变量解析
* 格式 以 Think. 打头的变量属于特殊模板变量
* @access public
* @param string $varStr 变量字符串
* @return string
*/
public function parseThinkVar($varStr)
{
if (is_array($varStr)) {
//用于正则替换回调函数
$varStr = $varStr[1];
}
$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] . '\']';
} elseif (C('COOKIE_PREFIX')) {
$parseStr = '$_COOKIE[\'' . C('COOKIE_PREFIX') . $vars[2] . '\']';
} else {
$parseStr = '$_COOKIE[\'' . $vars[2] . '\']';
}
break;
case 'SESSION':
if (isset($vars[3])) {
$parseStr = '$_SESSION[\'' . $vars[2] . '\'][\'' . $vars[3] . '\']';
} elseif (C('SESSION_PREFIX')) {
$parseStr = '$_SESSION[\'' . C('SESSION_PREFIX') . '\'][\'' . $vars[2] . '\']';
} else {
$parseStr = '$_SESSION[\'' . $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 = 'L("' . $vars[2] . '")';
break;
case 'CONFIG':$parseStr = 'C("' . $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;
case 'TEMPLATE':$parseStr = 'C("TEMPLATE_NAME")';
break;
case 'LDELIM':$parseStr = 'C("TMPL_L_DELIM")';
break;
case 'RDELIM':$parseStr = 'C("TMPL_R_DELIM")';
break;
default:if (defined($vars[1])) {
$parseStr = $vars[1];
}
}
}
return $parseStr;
}
// 获取标签定义
public function getTags()
{
return $this->tags;
}
}