From 0fd2530dcd8ad03b65d50a105788d1700c80b6a0 Mon Sep 17 00:00:00 2001 From: topnuomi <1130395124@qq.com> Date: Mon, 1 Jun 2020 19:36:15 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E9=AB=98=E8=87=AA=E5=B8=A6=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=BC=95=E6=93=8E=E7=9A=84=E5=AE=B9=E9=94=99=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/library/template/driver/Top.php | 10 +- .../library/template/driver/engine/Engine.php | 179 ++++-------------- .../library/template/driver/engine/Tags.php | 165 ++++++++++++++++ 3 files changed, 209 insertions(+), 145 deletions(-) create mode 100644 framework/library/template/driver/engine/Tags.php diff --git a/framework/library/template/driver/Top.php b/framework/library/template/driver/Top.php index ccca4ff..d477b4c 100644 --- a/framework/library/template/driver/Top.php +++ b/framework/library/template/driver/Top.php @@ -14,14 +14,14 @@ class Top implements TemplateIfs use Instance; /** - * @var null 模板引擎实现 + * @var Engine 模板引擎实现 */ private $engine = null; /** - * @var null 模板配置 + * @var array 模板配置 */ - private $config = null; + private $config = []; /** * @var bool 缓存状态 @@ -52,8 +52,8 @@ class Top implements TemplateIfs mkdir($this->config['compileDir'], 0755, true); } if (isset($this->config['tagLib']) && !empty($this->config['tagLib'])) { - foreach ($this->config['tagLib'] as $lib) { - $this->engine->loadTaglib($lib); + foreach ($this->config['tagLib'] as $prefix => $className) { + $this->engine->loadTaglib($prefix, $className); } } $content = $this->engine->compile(file_get_contents($filename)); diff --git a/framework/library/template/driver/engine/Engine.php b/framework/library/template/driver/engine/Engine.php index 2f7dca1..9ec5efb 100644 --- a/framework/library/template/driver/engine/Engine.php +++ b/framework/library/template/driver/engine/Engine.php @@ -6,7 +6,7 @@ use Exception; use top\traits\Instance; /** - * 模板标签库(支持模板继承) + * 模板标签解析 * Class Template * @package lib */ @@ -31,30 +31,19 @@ class Engine protected $tags = []; /** - * @var null 模板配置 + * @var array 模板配置 */ - protected $config = null; + protected $config = []; /** - * @var null 扩展标签库 + * @var array 标签库 */ - private $extend = []; + private $libs = []; /** - * @var array 扩展标签库类实例 + * @var array 标签库类实例 */ - private $extendInstance = []; - - /** - * @var array 默认标签定义 - */ - private $defaultTags = [ - 'php' => ['attr' => null, 'close' => 1], - 'if' => ['attr' => 'condition', 'close' => 1], - 'else' => ['attr' => 'condition', 'close' => 0], - 'loop' => ['attr' => 'name,id,key', 'close' => 1], - 'assign' => ['attr' => 'name,value', 'close' => 0] - ]; + private $libInstance = []; /** * 构造方法 @@ -79,10 +68,10 @@ class Engine */ private function parseExtend($template) { - $pattern = '/' . $this->left . 'extend.*?file=[\'"](.*?)[\'"].*?\/' . $this->right . '/is'; + $pattern = '/' . $this->left . 'extend\s+file[\s\S]*?=[\s\S]*?[\'"](.*?)[\'"][\s\S]*?\/' . $this->right . '/is'; preg_match($pattern, $template, $matches); if (!empty($matches)) { - $blockPattern = '/' . $this->left . 'block.*?name=[\'"](.*?)[\'"]' . $this->right; + $blockPattern = '/' . $this->left . 'block\s+name[\s\S]*?=[\s\S]*?[\'"](.*?)[\'"][\s\S]*?' . $this->right; $blockPattern .= '([\s\S]*?)' . $this->left . '\/block' . $this->right . '/is'; // 获得被继承的模板内容 $file = $this->config['dir'] . $matches[1] . '.' . ltrim($this->config['ext'], '.'); @@ -132,7 +121,7 @@ class Engine */ private function parseInclude($template) { - $pattern = '/' . $this->left . 'include.*?file=[\'"](.*?)[\'"].*?\/' . $this->right . '/is'; + $pattern = '/' . $this->left . 'include\s+file[\s\S]*?=[\s\S]*?[\'"](.*?)[\'"][\s\S]*?\/' . $this->right . '/is'; $template = preg_replace_callback($pattern, function ($result) { $string = null; $file = $this->config['dir'] . $result[1] . '.' . ltrim($this->config['ext'], '.'); @@ -155,7 +144,7 @@ class Engine */ private function hasInclude($template) { - $pattern = '/' . $this->left . 'include.*?file=[\'"](.*?)[\'"].*?\/' . $this->right . '/is'; + $pattern = '/' . $this->left . 'include\s+file[\s\S]*?=[\s\S]*?[\'"](.*?)[\'"][\s\S]*?\/' . $this->right . '/is'; preg_match($pattern, $template, $matches); return !empty($matches); } @@ -184,7 +173,6 @@ class Engine $content = $matches[1][$i]; } $replace[] = ''; - // $replace[] = $matches[0][$i]; } } $template = str_replace($search, $replace, $template); @@ -193,31 +181,35 @@ class Engine /** * 外部加载扩展标签 - * @param $lib + * @param $prefix + * @param $className */ - public function loadTaglib($lib) + public function loadTaglib($prefix, $className) { - $this->extend[] = $lib; + if ($prefix == 'default') { + throw new Exception('扩展标签库前缀不能为default'); + } + $this->libs[$prefix] = $className; } /** - * 标签处理 - * @param $template + * 获取所有标签 * @return null|string|string[] */ - private function parseTags($template) + private function getTags() { - foreach ($this->extend as $lib) { - $prefix = substr($lib, strrpos($lib, '\\') + 1); - $this->extendInstance[$prefix] = $object = new $lib; + $tags = []; + // 加入默认标签库 + $this->libs = array_merge(['default' => Tags::class,], $this->libs); + foreach ($this->libs as $prefix => $lib) { + $this->libInstance[$prefix] = $object = new $lib; foreach ($object->tags as $name => $tag) { - if (!isset($this->tags[$name]) && !isset($this->defaultTags[$name])) { - $this->tags[$prefix . ':' . $name] = $tag; + if (!isset($tags[$name])) { // 如果不存在则加入到标签库 + $tags[($prefix == 'default' ? '' : $prefix . ':') . $name] = $tag; } } } - $tags = array_merge($this->defaultTags, $this->tags); - return $this->_parseTags($template, $tags); + return $tags; } /** @@ -225,20 +217,20 @@ class Engine * @param $name * @param $attr * @param string $content - * @return null + * @return mixed */ private function getTagParseResult($name, $attr, $content = '') { // 如果是扩展标签则找到扩展类进行处理 if (strstr($name, ':')) { $tagInfo = explode(':', $name); - if (method_exists($this->extendInstance[$tagInfo[0]], '_' . $tagInfo[1])) { - return $this->extendInstance[$tagInfo[0]]->{'_' . $tagInfo[1]}($attr, $content); + if (method_exists($this->libInstance[$tagInfo[0]], '_' . $tagInfo[1])) { + return $this->libInstance[$tagInfo[0]]->{'_' . $tagInfo[1]}($attr, $content); } } - // 否则尝试自带标签处理 - else if (method_exists($this, '_' . $name)) { - return $this->{'_' . $name}($attr, $content); + // 否则尝试默认标签处理 + else if (method_exists($this->libInstance['default'], '_' . $name)) { + return $this->libInstance['default']->{'_' . $name}($attr, $content); } } @@ -248,9 +240,9 @@ class Engine * @param $tags * @return null|string|string[] */ - private function _parseTags($template, $tags) + private function parseTags($template) { - foreach ($tags as $name => $item) { + foreach ($this->getTags() as $name => $item) { $pattern = '/' . $this->left . '(?:(' . $name . ')\b(?>[^' . $this->right . ']*)|\/(' . $name . '))'; $pattern .= $this->right . '/is'; if ($item['close']) { @@ -336,11 +328,11 @@ class Engine private function getAttr($string, $tags = []) { $attr = []; - $attrPattern = '/[ +](.*?)=([\'"])(.*?)\\2/is'; + $attrPattern = '/\s+(.*?)=[\s\S]*?([\'"])(.*?)\\2/is'; preg_match_all($attrPattern, $string, $result); if (isset($result[0]) && !empty($result[0])) { foreach ($result[1] as $key => $value) { - $name = trim($value, ' '); + $name = str_replace([' ', "\t", PHP_EOL], '', $value); if (in_array($name, $tags)) { $attr[$name] = $result[3][$key]; } @@ -385,99 +377,6 @@ class Engine ], $template); } - /** - * php标签开始 - * @param $tag - * @param $content - * @return string - */ - private function _php($tag, $content) - { - return ''; - } - - /** - * if标签 - * @param $tag - * @param $content - * @return string - */ - private function _if($tag, $content) - { - $tag['condition'] = $this->_parseCondition($tag['condition']); - $parse = ''; - $parse .= $content; - $parse .= ''; - return $parse; - } - - /** - * else标签 - * @param $tag - * @return string - */ - private function _else($tag) - { - if (isset($tag['condition'])) { - $tag['condition'] = $this->_parseCondition($tag['condition']); - $parse = ''; - } else { - $parse = ''; - } - return $parse; - } - - /** - * 处理if/else标签的条件比较符 - * @param $condition - * @return mixed - */ - private function _parseCondition($condition) - { - return str_ireplace([ - ' eq ', - ' neq ', - ' lt ', - ' elt ', - ' gt ', - ' egt ', - ' heq ', - ' nheq ' - ], [ - ' == ', - ' != ', - ' < ', - ' <= ', - ' > ', - ' >= ', - ' === ', - ' !== ' - ], $condition); - } - - /** - * loop标签 - * @param $tag - * @param $content - * @return string - */ - private function _loop($tag, $content) - { - $parse = '' : '') . '$' . $tag['id'] . '): '; - $parse .= (isset($tag['key']) ? '$' . $tag['key'] . '++;' : '') . ' ?>'; - $parse .= $content; - $parse .= ''; - return $parse; - } - - private function _assign($tag) - { - $quot = (strstr($tag['value'], '\'')) ? '"' : '\''; - $parse = ''; - return $parse; - } - /** * 获取编译后的内容 * @param $template @@ -498,7 +397,7 @@ class Engine // 还原original内容 $template = $this->returnOriginal($template); - return '' . $template; + return '' . $template; } } diff --git a/framework/library/template/driver/engine/Tags.php b/framework/library/template/driver/engine/Tags.php new file mode 100644 index 0000000..65a0310 --- /dev/null +++ b/framework/library/template/driver/engine/Tags.php @@ -0,0 +1,165 @@ + ['attr' => '', 'close' => 1], + 'if' => ['attr' => 'condition', 'close' => 1], + 'else' => ['attr' => 'condition', 'close' => 0], + 'loop' => ['attr' => 'name,id,key', 'close' => 1], + 'assign' => ['attr' => 'name,value', 'close' => 0], + 'switch' => ['attr' => 'name', 'close' => 1], + 'case' => ['attr' => 'value', 'close' => 1], + ]; + + + /** + * php标签 + * @param $attr + * @param $content + * @return string + */ + public function _php($attr, $content) + { + return ''; + } + + /** + * if标签 + * @param $attr + * @param $content + * @return string + */ + public function _if($attr, $content) + { + $attr['condition'] = $this->_parseCondition($attr['condition']); + $parse = ''; + $parse .= $content; + $parse .= ''; + return $parse; + } + + /** + * else标签 + * @param $attr + * @return string + */ + public function _else($attr) + { + if (isset($attr['condition'])) { + $attr['condition'] = $this->_parseCondition($attr['condition']); + $parse = ''; + } else { + $parse = ''; + } + return $parse; + } + + /** + * 处理if/else标签的条件比较符 + * @param $condition + * @return mixed + */ + public function _parseCondition($condition) + { + return str_ireplace([ + ' eq ', + ' neq ', + ' lt ', + ' elt ', + ' gt ', + ' egt ', + ' heq ', + ' nheq ' + ], [ + ' == ', + ' != ', + ' < ', + ' <= ', + ' > ', + ' >= ', + ' === ', + ' !== ' + ], $condition); + } + + /** + * loop标签 + * @param $tag + * @param $content + * @return string + */ + public function _loop($attr, $content) + { + $parse = '' : '') . '$' . $attr['id'] . '): '; + $parse .= (isset($attr['key']) ? '$' . $attr['key'] . '++;' : '') . ' ?>'; + $parse .= $content; + $parse .= ''; + return $parse; + } + + /** + * 模版变量赋值 + * @param $attr + * @return string + */ + public function _assign($attr) + { + if (isset($attr['name']) && isset($attr['value'])) { + $quot = (strstr($attr['value'], '\'')) ? '"' : '\''; + $parse = ''; + return $parse; + } + throw new Exception('assign标签必须拥有属性:' . $this->defaultTags['assign']['attr']); + } + + /** + * switch标签 + * @param $attr + * @param $content + * @return string + */ + public function _switch($attr, $content) + { + if (isset($attr['name'])) { + $parse = ''; + $parse .= $content; + $parse .= ''; + return $parse; + } + throw new Exception('switch标签必须拥有属性:' . $this->defaultTags['switch']['attr']); + } + + /** + * switch标签case处理 + * @param $attr + * @param $content + * @return string + */ + public function _case($attr, $content) + { + if (isset($attr['value'])) { + $quot = (strstr($attr['value'], '\'')) ? '"' : '\''; + $parse = ''; + $parse .= $content; + $parse .= ''; + } else { + $parse = ''; + $parse .= $content; + } + return $parse; + } +}