PageRenderTime 33ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/upload/wind/viewer/compiler/WindViewTemplate.php

https://gitlab.com/wuhang2003/phpwind
PHP | 224 lines | 95 code | 14 blank | 115 comment | 10 complexity | e64624a517cef98b3995278f108e720f MD5 | raw file
  1. <?php
  2. Wind::import('WIND:viewer.AbstractWindViewTemplate');
  3. Wind::import('WIND:utility.WindFile');
  4. /**
  5. * 模板编译类
  6. *
  7. * 职责:进行模板编译,该类接收一个需要编译的模板文件地址,获取该模板内容并进行编译处理然后返回该内容.
  8. * 组件配置信息,可以通过config标签实现标签扩展支持:<code>
  9. * 'template' => array(
  10. * 'path' => 'WIND:viewer.compiler.WindViewTemplate',
  11. * 'scope' => 'prototype',
  12. * 'config' => array('resource' => ''),
  13. * )
  14. * <config>
  15. * //配置信息
  16. * <support-tags>
  17. * <!-- 标签配置:name: 标签名字, tag:具体的标签, pattern:匹配表达式 , compiler:解析类文件-->
  18. * <!--<tag name='' tag='' pattern='' compiler='' /> -->
  19. * </support-tags>
  20. * </config>
  21. * </code>
  22. * 扩展名为'test'的标签扩展配置如下,需要定义标签名称,用于匹配该标签的正则表达式(可以为空,为空则调用默认的正则标签匹配,通常情况下请保持为空),
  23. * 以及用于解析该标签的标签编译器(标签编译器需要继承AbstractWindTemplateCompiler):<code>
  24. * <support-tags>
  25. * <tag name='test' tag='test' pattern='<(test)[^<>\n]*(\/>|>[^<>]*<\/\1>)' compiler='TEST:TestTemplateCompiler' />
  26. * </support-tags>
  27. * </code>
  28. * @author Qiong Wu <papa0924@gmail.com>
  29. * @copyright ©2003-2103 phpwind.com
  30. * @license http://www.windframework.com
  31. * @version $Id: WindViewTemplate.php 3904 2013-01-08 07:01:26Z yishuo $
  32. * @package viewer
  33. * @subpackage compiler
  34. */
  35. class WindViewTemplate extends AbstractWindViewTemplate {
  36. /**
  37. * match后的模块文件块
  38. *
  39. * @var array
  40. */
  41. protected $compiledBlockData = array();
  42. /**
  43. * @var WindHandlerInterceptorChain
  44. */
  45. protected $windHandlerInterceptorChain = null;
  46. protected $_compilerCache = array();
  47. /* (non-PHPdoc)
  48. * @see AbstractWindViewTemplate::doCompile()
  49. */
  50. protected function doCompile($content, $windViewerResolver = null) {
  51. try {
  52. $content = $this->registerTags($content, $windViewerResolver);
  53. if ($this->windHandlerInterceptorChain !== null) {
  54. $this->windHandlerInterceptorChain->getHandler()->handle();
  55. }
  56. foreach (array_reverse($this->compiledBlockData) as $key => $value) {
  57. if (!$key) continue;
  58. $content = str_replace($this->getBlockTag($key), ($value ? $value : ' '), $content);
  59. }
  60. $content = preg_replace('/\?>(\s|\n)*?<\?php/i', "\r\n", $content);
  61. return $content;
  62. } catch (Exception $e) {
  63. throw new WindViewException(
  64. '[viewer.WindViewTemplate.doCompile] compile fail.' . $e->getMessage(),
  65. WindViewException::ERROR_SYSTEM_ERROR);
  66. }
  67. }
  68. /**
  69. * 注册支持的标签并返回注册后的模板内容
  70. *
  71. * 解析模板内容,并将匹配到的标签内容块注册到相应的标签编译器中并初始化标签解析器处理链.
  72. * @param string $content
  73. * @param WindViewerResolver $windViewerResolver
  74. * @return string
  75. */
  76. private function registerTags($content, $windViewerResolver = null) {
  77. foreach ((array) $this->getTags() as $key => $value) {
  78. $compiler = isset($value['compiler']) ? $value['compiler'] : '';
  79. $regex = isset($value['pattern']) ? $value['pattern'] : '';
  80. $tag = isset($value['tag']) ? $value['tag'] : '';
  81. if (!$compiler || !$tag) continue;
  82. if ($regex === '') $regex = '/<(' . preg_quote($tag) . ')(.*?)(\/>|>(.*?)<\/\1>)/is';
  83. $content = $this->creatTagCompiler($content, $compiler, $regex, $windViewerResolver);
  84. }
  85. return $content;
  86. }
  87. /**
  88. * 创建对应标签的解析器类实例对象,并加载到处理链中.
  89. *
  90. * @param string content 模板内容
  91. * @param string compiler 标签编译器
  92. * @param string regex 正则表达式
  93. * @param WindViewerResolver $windViewerResolver 默认为null
  94. * @return string 返回处理后的模板内容
  95. */
  96. private function creatTagCompiler($content, $compiler, $regex, $windViewerResolver = null) {
  97. $content = preg_replace_callback($regex, array($this, '_creatTagCompiler'), $content);
  98. if ($this->windHandlerInterceptorChain === null) {
  99. $this->windHandlerInterceptorChain = new WindHandlerInterceptorChain();
  100. }
  101. $_compilerClass = Wind::import($compiler);
  102. $this->windHandlerInterceptorChain->addInterceptors(
  103. new $_compilerClass($this->_compilerCache, $this, $windViewerResolver,
  104. $this->getRequest(), $this->getResponse()));
  105. $this->_compilerCache = array();
  106. return $content;
  107. }
  108. /**
  109. * 返回当前解析器中所有注册进来的标签集合
  110. *
  111. * @return array
  112. */
  113. protected function getTags() {
  114. $_tags['internal'] = $this->createTag('internal', 'WIND:viewer.compiler.WindTemplateCompilerInternal',
  115. '/<\?php.*?\?>/is');
  116. /*标签体增加在该位置*/
  117. $_tags['template'] = $this->createTag('template',
  118. 'WIND:viewer.compiler.WindTemplateCompilerTemplate');
  119. //$_tags['page'] = $this->createTag('page', 'WIND:viewer.compiler.WindTemplateCompilerPage');
  120. $_tags['action'] = $this->createTag('action',
  121. 'WIND:viewer.compiler.WindTemplateCompilerAction');
  122. //$_tags['component'] = $this->createTag('component', 'WIND:viewer.compiler.WindTemplateCompilerComponent');
  123. $_tags['token'] = $this->createTag('token',
  124. 'WIND:viewer.compiler.WindTemplateCompilerToken');
  125. $_tags['lang'] = $this->createTag('lang', 'WIND:viewer.compiler.WindTemplateCompilerLang');
  126. $_tags = array_merge($_tags, $this->getConfig('support-tags', '', array()));
  127. /*标签解析结束*/
  128. $_tags['expression'] = $this->createTag('expression',
  129. 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/({@|{\$[\w$]{1})[^}{@\n]*}/i');
  130. $_tags = array_merge($_tags, $this->getConfig('support-tags-end', '', array()));
  131. //$_tags['echo'] = $this->createTag('echo', 'WIND:viewer.compiler.WindTemplateCompilerEcho', '/\$[\w_]+/i');
  132. /* 块编译标签,嵌套变量处理 */
  133. //$_tags['script1'] = $this->createTag('script1', 'WIND:viewer.compiler.WindTemplateCompilerScript', '/<!--\[[\w\s]*\]>(.|\n)*<!\[[\w\s]*\]-->/Ui');
  134. //$_tags['script'] = $this->createTag('script', 'WIND:viewer.compiler.WindTemplateCompilerScript', '/<(script)[^<>\n]*(\/>|>(.|\n)*<\/\1>)/Ui');
  135. //$_tags['link'] = $this->createTag('link', 'WIND:viewer.compiler.WindTemplateCompilerCss');
  136. //$_tags['style'] = $this->createTag('style', 'WIND:viewer.compiler.WindTemplateCompilerCss');
  137. return $_tags;
  138. }
  139. /**
  140. * 创建tag编译解析的配置
  141. *
  142. * @param string $tag 标签名称
  143. * @param string $class 编译器类新型
  144. * @param stirng $pattern 正则表达式,用于匹配标签 默认为空
  145. * @return array
  146. */
  147. private function createTag($tag, $class, $pattern = '') {
  148. return array('tag' => $tag, 'pattern' => $pattern, 'compiler' => $class);
  149. }
  150. /**
  151. * 将标签匹配到的模板内容设置到缓存中,并返回标识位设置到模板中进行内容占为
  152. *
  153. * @param string $content
  154. * @return mixed
  155. */
  156. private function _creatTagCompiler($content) {
  157. $_content = $content[0];
  158. if (!$_content) return '';
  159. $key = $this->getCompiledBlockKey();
  160. $this->_compilerCache[] = array($key, $_content);
  161. return $this->getBlockTag($key);
  162. }
  163. /**
  164. * 对模板块存储进行标签处理
  165. * 将Key串 'HhQWFLtU0LSA3nLPLHHXMtTP3EfMtN3FsxLOR1nfYC5OiZTQri' 处理为
  166. * <pw-wind key='HhQWFLtU0LSA3nLPLHHXMtTP3EfMtN3FsxLOR1nfYC5OiZTQri' />
  167. * 在模板中进行位置标识
  168. *
  169. * @param string $key 索引
  170. * @return string|mixed 处理后结果
  171. */
  172. private function getBlockTag($key) {
  173. return '#' . $key . '#';
  174. }
  175. /**
  176. * 获得切分后块编译缓存Key值,Key值为一个50位的随机字符串,当产生重复串时继续查找
  177. *
  178. * @return string
  179. */
  180. protected function getCompiledBlockKey() {
  181. $key = WindUtility::generateRandStr(50);
  182. if (key_exists($key, $this->compiledBlockData)) {
  183. return $this->getCompiledBlockKey();
  184. }
  185. return $key;
  186. }
  187. /**
  188. * 返回编译后结果,根据Key值检索编译后结果,并返回.当key值为空时返回全部数据
  189. *
  190. * @param string $key
  191. * @return string|array
  192. */
  193. public function getCompiledBlockData($key = '') {
  194. if ($key)
  195. return isset($this->compiledBlockData[$key]) ? $this->compiledBlockData[$key] : '';
  196. else
  197. return $this->compiledBlockData;
  198. }
  199. /**
  200. * 根据key值保存编译后的模板块
  201. *
  202. * @param string $key 索引
  203. * @param string $compiledBlockData 编译结果
  204. * @return void
  205. */
  206. public function setCompiledBlockData($key, $compiledBlockData) {
  207. if ($key) $this->compiledBlockData[$key] = $compiledBlockData;
  208. }
  209. }
  210. ?>