think\template\TagLib::parseTag PHP Метод

parseTag() публичный Метод

按签标库替换页面中的标签
public parseTag ( string &$content, string $lib = '' ) : void
$content string 模板内容
$lib string 标签库名
Результат 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;
    }