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;
}