Total Complexity | 217 |
Total Lines | 1296 |
Duplicated Lines | 0 % |
Changes | 0 |
Complex classes like Template often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Template, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class Template |
||
22 | { |
||
23 | protected $app; |
||
24 | /** |
||
25 | * 模板变量 |
||
26 | * @var array |
||
27 | */ |
||
28 | protected $data = []; |
||
29 | |||
30 | /** |
||
31 | * 模板配置参数 |
||
32 | * @var array |
||
33 | */ |
||
34 | protected $config = [ |
||
35 | 'view_path' => '', // 模板路径 |
||
36 | 'view_base' => '', |
||
37 | 'view_suffix' => 'html', // 默认模板文件后缀 |
||
38 | 'view_depr' => DIRECTORY_SEPARATOR, |
||
39 | 'cache_suffix' => 'php', // 默认模板缓存后缀 |
||
40 | 'tpl_deny_func_list' => 'echo,exit', // 模板引擎禁用函数 |
||
41 | 'tpl_deny_php' => false, // 默认模板引擎是否禁用PHP原生代码 |
||
42 | 'tpl_begin' => '{', // 模板引擎普通标签开始标记 |
||
43 | 'tpl_end' => '}', // 模板引擎普通标签结束标记 |
||
44 | 'strip_space' => false, // 是否去除模板文件里面的html空格与换行 |
||
45 | 'tpl_cache' => true, // 是否开启模板编译缓存,设为false则每次都会重新编译 |
||
46 | 'compile_type' => 'file', // 模板编译类型 |
||
47 | 'cache_prefix' => '', // 模板缓存前缀标识,可以动态改变 |
||
48 | 'cache_time' => 0, // 模板缓存有效期 0 为永久,(以数字为值,单位:秒) |
||
49 | 'layout_on' => false, // 布局模板开关 |
||
50 | 'layout_name' => 'layout', // 布局模板入口文件 |
||
51 | 'layout_item' => '{__CONTENT__}', // 布局模板的内容替换标识 |
||
52 | 'taglib_begin' => '{', // 标签库标签开始标记 |
||
53 | 'taglib_end' => '}', // 标签库标签结束标记 |
||
54 | 'taglib_load' => true, // 是否使用内置标签库之外的其它标签库,默认自动检测 |
||
55 | 'taglib_build_in' => 'cx', // 内置标签库名称(标签使用不必指定标签库名称),以逗号分隔 注意解析顺序 |
||
56 | 'taglib_pre_load' => '', // 需要额外加载的标签库(须指定标签库名称),多个以逗号分隔 |
||
57 | 'display_cache' => false, // 模板渲染缓存 |
||
58 | 'cache_id' => '', // 模板缓存ID |
||
59 | 'tpl_replace_string' => [], |
||
60 | 'tpl_var_identify' => 'array', // .语法变量识别,array|object|'', 为空时自动识别 |
||
61 | 'default_filter' => 'htmlentities', // 默认过滤方法 用于普通标签输出 |
||
62 | ]; |
||
63 | |||
64 | /** |
||
65 | * 保留内容信息 |
||
66 | * @var array |
||
67 | */ |
||
68 | private $literal = []; |
||
69 | |||
70 | /** |
||
71 | * 模板包含信息 |
||
72 | * @var array |
||
73 | */ |
||
74 | private $includeFile = []; |
||
75 | |||
76 | /** |
||
77 | * 模板存储对象 |
||
78 | * @var object |
||
79 | */ |
||
80 | protected $storage; |
||
81 | |||
82 | /** |
||
83 | * 架构函数 |
||
84 | * @access public |
||
85 | * @param array $config |
||
86 | */ |
||
87 | public function __construct(App $app, array $config = []) |
||
88 | { |
||
89 | $this->app = $app; |
||
90 | $this->config['cache_path'] = $app->getRuntimePath() . 'temp/'; |
||
91 | $this->config = array_merge($this->config, $config); |
||
92 | |||
93 | $this->config['taglib_begin_origin'] = $this->config['taglib_begin']; |
||
94 | $this->config['taglib_end_origin'] = $this->config['taglib_end']; |
||
95 | |||
96 | $this->config['taglib_begin'] = preg_quote($this->config['taglib_begin'], '/'); |
||
97 | $this->config['taglib_end'] = preg_quote($this->config['taglib_end'], '/'); |
||
98 | $this->config['tpl_begin'] = preg_quote($this->config['tpl_begin'], '/'); |
||
99 | $this->config['tpl_end'] = preg_quote($this->config['tpl_end'], '/'); |
||
100 | |||
101 | // 初始化模板编译存储器 |
||
102 | $type = $this->config['compile_type'] ? $this->config['compile_type'] : 'File'; |
||
103 | |||
104 | $this->storage = Loader::factory($type, '\\think\\template\\driver\\', null); |
||
105 | } |
||
106 | |||
107 | public static function __make(Config $config) |
||
1 ignored issue
–
show
|
|||
108 | { |
||
109 | return new static($config->pull('template')); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * 模板变量赋值 |
||
114 | * @access public |
||
115 | * @param mixed $name |
||
116 | * @param mixed $value |
||
117 | * @return void |
||
118 | */ |
||
119 | public function assign($name, $value = '') |
||
120 | { |
||
121 | if (is_array($name)) { |
||
122 | $this->data = array_merge($this->data, $name); |
||
123 | } else { |
||
124 | $this->data[$name] = $value; |
||
125 | } |
||
126 | } |
||
127 | |||
128 | /** |
||
129 | * 模板引擎参数赋值 |
||
130 | * @access public |
||
131 | * @param mixed $name |
||
132 | * @param mixed $value |
||
133 | */ |
||
134 | public function __set($name, $value) |
||
135 | { |
||
136 | $this->config[$name] = $value; |
||
137 | } |
||
138 | |||
139 | /** |
||
140 | * 模板引擎配置项 |
||
141 | * @access public |
||
142 | * @param array|string $config |
||
143 | * @return void|array |
||
144 | */ |
||
145 | public function config($config) |
||
146 | { |
||
147 | if (is_array($config)) { |
||
148 | $this->config = array_merge($this->config, $config); |
||
149 | } elseif (isset($this->config[$config])) { |
||
150 | return $this->config[$config]; |
||
151 | } |
||
152 | } |
||
153 | |||
154 | /** |
||
155 | * 模板变量获取 |
||
156 | * @access public |
||
157 | * @param string $name 变量名 |
||
158 | * @return mixed |
||
159 | */ |
||
160 | public function get($name = '') |
||
161 | { |
||
162 | if ('' == $name) { |
||
163 | return $this->data; |
||
164 | } |
||
165 | |||
166 | $data = $this->data; |
||
167 | |||
168 | foreach (explode('.', $name) as $key => $val) { |
||
169 | if (isset($data[$val])) { |
||
170 | $data = $data[$val]; |
||
171 | } else { |
||
172 | $data = null; |
||
173 | break; |
||
174 | } |
||
175 | } |
||
176 | |||
177 | return $data; |
||
178 | } |
||
179 | |||
180 | /** |
||
181 | * 渲染模板文件 |
||
182 | * @access public |
||
183 | * @param string $template 模板文件 |
||
184 | * @param array $vars 模板变量 |
||
185 | * @param array $config 模板参数 |
||
186 | * @return void |
||
187 | */ |
||
188 | public function fetch($template, $vars = [], $config = []) |
||
189 | { |
||
190 | if ($vars) { |
||
191 | $this->data = $vars; |
||
192 | } |
||
193 | |||
194 | if ($config) { |
||
195 | $this->config($config); |
||
196 | } |
||
197 | |||
198 | $cache = $this->app['cache']; |
||
199 | |||
200 | if (!empty($this->config['cache_id']) && $this->config['display_cache']) { |
||
201 | // 读取渲染缓存 |
||
202 | $cacheContent = $cache->get($this->config['cache_id']); |
||
203 | |||
204 | if (false !== $cacheContent) { |
||
205 | echo $cacheContent; |
||
206 | return; |
||
207 | } |
||
208 | } |
||
209 | |||
210 | $template = $this->parseTemplateFile($template); |
||
211 | |||
212 | if ($template) { |
||
213 | $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($this->config['layout_on'] . $this->config['layout_name'] . $template) . '.' . ltrim($this->config['cache_suffix'], '.'); |
||
214 | |||
215 | if (!$this->checkCache($cacheFile)) { |
||
216 | // 缓存无效 重新模板编译 |
||
217 | $content = file_get_contents($template); |
||
218 | $this->compiler($content, $cacheFile); |
||
219 | } |
||
220 | |||
221 | // 页面缓存 |
||
222 | ob_start(); |
||
223 | ob_implicit_flush(0); |
||
224 | |||
225 | // 读取编译存储 |
||
226 | $this->storage->read($cacheFile, $this->data); |
||
227 | |||
228 | // 获取并清空缓存 |
||
229 | $content = ob_get_clean(); |
||
230 | |||
231 | if (!empty($this->config['cache_id']) && $this->config['display_cache']) { |
||
232 | // 缓存页面输出 |
||
233 | $cache->set($this->config['cache_id'], $content, $this->config['cache_time']); |
||
234 | } |
||
235 | |||
236 | echo $content; |
||
237 | } |
||
238 | } |
||
239 | |||
240 | /** |
||
241 | * 渲染模板内容 |
||
242 | * @access public |
||
243 | * @param string $content 模板内容 |
||
244 | * @param array $vars 模板变量 |
||
245 | * @param array $config 模板参数 |
||
246 | * @return void |
||
247 | */ |
||
248 | public function display($content, $vars = [], $config = []) |
||
249 | { |
||
250 | if ($vars) { |
||
251 | $this->data = $vars; |
||
252 | } |
||
253 | |||
254 | if ($config) { |
||
255 | $this->config($config); |
||
256 | } |
||
257 | |||
258 | $cacheFile = $this->config['cache_path'] . $this->config['cache_prefix'] . md5($content) . '.' . ltrim($this->config['cache_suffix'], '.'); |
||
259 | |||
260 | if (!$this->checkCache($cacheFile)) { |
||
261 | // 缓存无效 模板编译 |
||
262 | $this->compiler($content, $cacheFile); |
||
263 | } |
||
264 | |||
265 | // 读取编译存储 |
||
266 | $this->storage->read($cacheFile, $this->data); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * 设置布局 |
||
271 | * @access public |
||
272 | * @param mixed $name 布局模板名称 false 则关闭布局 |
||
273 | * @param string $replace 布局模板内容替换标识 |
||
274 | * @return object |
||
275 | */ |
||
276 | public function layout($name, $replace = '') |
||
277 | { |
||
278 | if (false === $name) { |
||
279 | // 关闭布局 |
||
280 | $this->config['layout_on'] = false; |
||
281 | } else { |
||
282 | // 开启布局 |
||
283 | $this->config['layout_on'] = true; |
||
284 | |||
285 | // 名称必须为字符串 |
||
286 | if (is_string($name)) { |
||
287 | $this->config['layout_name'] = $name; |
||
288 | } |
||
289 | |||
290 | if (!empty($replace)) { |
||
291 | $this->config['layout_item'] = $replace; |
||
292 | } |
||
293 | } |
||
294 | |||
295 | return $this; |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * 检查编译缓存是否有效 |
||
300 | * 如果无效则需要重新编译 |
||
301 | * @access private |
||
302 | * @param string $cacheFile 缓存文件名 |
||
303 | * @return boolean |
||
304 | */ |
||
305 | private function checkCache($cacheFile) |
||
306 | { |
||
307 | if (!$this->config['tpl_cache'] || !is_file($cacheFile) || !$handle = @fopen($cacheFile, "r")) { |
||
308 | return false; |
||
309 | } |
||
310 | |||
311 | // 读取第一行 |
||
312 | preg_match('/\/\*(.+?)\*\//', fgets($handle), $matches); |
||
313 | |||
314 | if (!isset($matches[1])) { |
||
315 | return false; |
||
316 | } |
||
317 | |||
318 | $includeFile = unserialize($matches[1]); |
||
319 | |||
320 | if (!is_array($includeFile)) { |
||
321 | return false; |
||
322 | } |
||
323 | |||
324 | // 检查模板文件是否有更新 |
||
325 | foreach ($includeFile as $path => $time) { |
||
326 | if (is_file($path) && filemtime($path) > $time) { |
||
327 | // 模板文件如果有更新则缓存需要更新 |
||
328 | return false; |
||
329 | } |
||
330 | } |
||
331 | |||
332 | // 检查编译存储是否有效 |
||
333 | return $this->storage->check($cacheFile, $this->config['cache_time']); |
||
334 | } |
||
335 | |||
336 | /** |
||
337 | * 检查编译缓存是否存在 |
||
338 | * @access public |
||
339 | * @param string $cacheId 缓存的id |
||
340 | * @return boolean |
||
341 | */ |
||
342 | public function isCache($cacheId) |
||
343 | { |
||
344 | if ($cacheId && $this->config['display_cache']) { |
||
345 | // 缓存页面输出 |
||
346 | return $this->app['cache']->has($cacheId); |
||
347 | } |
||
348 | |||
349 | return false; |
||
350 | } |
||
351 | |||
352 | /** |
||
353 | * 编译模板文件内容 |
||
354 | * @access private |
||
355 | * @param string $content 模板内容 |
||
356 | * @param string $cacheFile 缓存文件名 |
||
357 | * @return void |
||
358 | */ |
||
359 | private function compiler(&$content, $cacheFile) |
||
360 | { |
||
361 | // 判断是否启用布局 |
||
362 | if ($this->config['layout_on']) { |
||
363 | if (false !== strpos($content, '{__NOLAYOUT__}')) { |
||
364 | // 可以单独定义不使用布局 |
||
365 | $content = str_replace('{__NOLAYOUT__}', '', $content); |
||
366 | } else { |
||
367 | // 读取布局模板 |
||
368 | $layoutFile = $this->parseTemplateFile($this->config['layout_name']); |
||
369 | |||
370 | if ($layoutFile) { |
||
371 | // 替换布局的主体内容 |
||
372 | $content = str_replace($this->config['layout_item'], $content, file_get_contents($layoutFile)); |
||
373 | } |
||
374 | } |
||
375 | } else { |
||
376 | $content = str_replace('{__NOLAYOUT__}', '', $content); |
||
377 | } |
||
378 | |||
379 | // 模板解析 |
||
380 | $this->parse($content); |
||
381 | |||
382 | if ($this->config['strip_space']) { |
||
383 | /* 去除html空格与换行 */ |
||
384 | $find = ['~>\s+<~', '~>(\s+\n|\r)~']; |
||
385 | $replace = ['><', '>']; |
||
386 | $content = preg_replace($find, $replace, $content); |
||
387 | } |
||
388 | |||
389 | // 优化生成的php代码 |
||
390 | $content = preg_replace('/\?>\s*<\?php\s(?!echo\b|\bend)/s', '', $content); |
||
391 | |||
392 | // 模板过滤输出 |
||
393 | $replace = $this->config['tpl_replace_string']; |
||
394 | $content = str_replace(array_keys($replace), array_values($replace), $content); |
||
395 | |||
396 | // 添加安全代码及模板引用记录 |
||
397 | $content = '<?php /*' . serialize($this->includeFile) . '*/ ?>' . "\n" . $content; |
||
398 | // 编译存储 |
||
399 | $this->storage->write($cacheFile, $content); |
||
400 | |||
401 | $this->includeFile = []; |
||
402 | } |
||
403 | |||
404 | /** |
||
405 | * 模板解析入口 |
||
406 | * 支持普通标签和TagLib解析 支持自定义标签库 |
||
407 | * @access public |
||
408 | * @param string $content 要解析的模板内容 |
||
409 | * @return void |
||
410 | */ |
||
411 | public function parse(&$content) |
||
412 | { |
||
413 | // 内容为空不解析 |
||
414 | if (empty($content)) { |
||
415 | return; |
||
416 | } |
||
417 | |||
418 | // 替换literal标签内容 |
||
419 | $this->parseLiteral($content); |
||
420 | |||
421 | // 解析继承 |
||
422 | $this->parseExtend($content); |
||
423 | |||
424 | // 解析布局 |
||
425 | $this->parseLayout($content); |
||
426 | |||
427 | // 检查include语法 |
||
428 | $this->parseInclude($content); |
||
429 | |||
430 | // 替换包含文件中literal标签内容 |
||
431 | $this->parseLiteral($content); |
||
432 | |||
433 | // 检查PHP语法 |
||
434 | $this->parsePhp($content); |
||
435 | |||
436 | // 获取需要引入的标签库列表 |
||
437 | // 标签库只需要定义一次,允许引入多个一次 |
||
438 | // 一般放在文件的最前面 |
||
439 | // 格式:<taglib name="html,mytag..." /> |
||
440 | // 当TAGLIB_LOAD配置为true时才会进行检测 |
||
441 | if ($this->config['taglib_load']) { |
||
442 | $tagLibs = $this->getIncludeTagLib($content); |
||
443 | |||
444 | if (!empty($tagLibs)) { |
||
445 | // 对导入的TagLib进行解析 |
||
446 | foreach ($tagLibs as $tagLibName) { |
||
447 | $this->parseTagLib($tagLibName, $content); |
||
448 | } |
||
449 | } |
||
450 | } |
||
451 | |||
452 | // 预先加载的标签库 无需在每个模板中使用taglib标签加载 但必须使用标签库XML前缀 |
||
453 | if ($this->config['taglib_pre_load']) { |
||
454 | $tagLibs = explode(',', $this->config['taglib_pre_load']); |
||
455 | |||
456 | foreach ($tagLibs as $tag) { |
||
457 | $this->parseTagLib($tag, $content); |
||
458 | } |
||
459 | } |
||
460 | |||
461 | // 内置标签库 无需使用taglib标签导入就可以使用 并且不需使用标签库XML前缀 |
||
462 | $tagLibs = explode(',', $this->config['taglib_build_in']); |
||
463 | |||
464 | foreach ($tagLibs as $tag) { |
||
465 | $this->parseTagLib($tag, $content, true); |
||
466 | } |
||
467 | |||
468 | // 解析普通模板标签 {$tagName} |
||
469 | $this->parseTag($content); |
||
470 | |||
471 | // 还原被替换的Literal标签 |
||
472 | $this->parseLiteral($content, true); |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * 检查PHP语法 |
||
477 | * @access private |
||
478 | * @param string $content 要解析的模板内容 |
||
479 | * @return void |
||
480 | * @throws \think\Exception |
||
481 | */ |
||
482 | private function parsePhp(&$content) |
||
483 | { |
||
484 | // 短标签的情况要将<?标签用echo方式输出 否则无法正常输出xml标识 |
||
485 | $content = preg_replace('/(<\?(?!php|=|$))/i', '<?php echo \'\\1\'; ?>' . "\n", $content); |
||
486 | |||
487 | // PHP语法检查 |
||
488 | if ($this->config['tpl_deny_php'] && false !== strpos($content, '<?php')) { |
||
489 | throw new Exception('not allow php tag'); |
||
490 | } |
||
491 | } |
||
492 | |||
493 | /** |
||
494 | * 解析模板中的布局标签 |
||
495 | * @access private |
||
496 | * @param string $content 要解析的模板内容 |
||
497 | * @return void |
||
498 | */ |
||
499 | private function parseLayout(&$content) |
||
500 | { |
||
501 | // 读取模板中的布局标签 |
||
502 | if (preg_match($this->getRegex('layout'), $content, $matches)) { |
||
503 | // 替换Layout标签 |
||
504 | $content = str_replace($matches[0], '', $content); |
||
505 | // 解析Layout标签 |
||
506 | $array = $this->parseAttr($matches[0]); |
||
507 | |||
508 | if (!$this->config['layout_on'] || $this->config['layout_name'] != $array['name']) { |
||
509 | // 读取布局模板 |
||
510 | $layoutFile = $this->parseTemplateFile($array['name']); |
||
511 | |||
512 | if ($layoutFile) { |
||
513 | $replace = isset($array['replace']) ? $array['replace'] : $this->config['layout_item']; |
||
514 | // 替换布局的主体内容 |
||
515 | $content = str_replace($replace, $content, file_get_contents($layoutFile)); |
||
516 | } |
||
517 | } |
||
518 | } else { |
||
519 | $content = str_replace('{__NOLAYOUT__}', '', $content); |
||
520 | } |
||
521 | } |
||
522 | |||
523 | /** |
||
524 | * 解析模板中的include标签 |
||
525 | * @access private |
||
526 | * @param string $content 要解析的模板内容 |
||
527 | * @return void |
||
528 | */ |
||
529 | private function parseInclude(&$content) |
||
530 | { |
||
531 | $regex = $this->getRegex('include'); |
||
532 | $func = function ($template) use (&$func, &$regex, &$content) { |
||
533 | if (preg_match_all($regex, $template, $matches, PREG_SET_ORDER)) { |
||
534 | foreach ($matches as $match) { |
||
535 | $array = $this->parseAttr($match[0]); |
||
536 | $file = $array['file']; |
||
537 | unset($array['file']); |
||
538 | |||
539 | // 分析模板文件名并读取内容 |
||
540 | $parseStr = $this->parseTemplateName($file); |
||
541 | |||
542 | foreach ($array as $k => $v) { |
||
543 | // 以$开头字符串转换成模板变量 |
||
544 | if (0 === strpos($v, '$')) { |
||
545 | $v = $this->get(substr($v, 1)); |
||
546 | } |
||
547 | |||
548 | $parseStr = str_replace('[' . $k . ']', $v, $parseStr); |
||
549 | } |
||
550 | |||
551 | $content = str_replace($match[0], $parseStr, $content); |
||
552 | // 再次对包含文件进行模板分析 |
||
553 | $func($parseStr); |
||
554 | } |
||
555 | unset($matches); |
||
556 | } |
||
557 | }; |
||
558 | |||
559 | // 替换模板中的include标签 |
||
560 | $func($content); |
||
561 | } |
||
562 | |||
563 | /** |
||
564 | * 解析模板中的extend标签 |
||
565 | * @access private |
||
566 | * @param string $content 要解析的模板内容 |
||
567 | * @return void |
||
568 | */ |
||
569 | private function parseExtend(&$content) |
||
570 | { |
||
571 | $regex = $this->getRegex('extend'); |
||
572 | $array = $blocks = $baseBlocks = []; |
||
573 | $extend = ''; |
||
574 | |||
575 | $func = function ($template) use (&$func, &$regex, &$array, &$extend, &$blocks, &$baseBlocks) { |
||
576 | if (preg_match($regex, $template, $matches)) { |
||
577 | if (!isset($array[$matches['name']])) { |
||
578 | $array[$matches['name']] = 1; |
||
579 | // 读取继承模板 |
||
580 | $extend = $this->parseTemplateName($matches['name']); |
||
581 | |||
582 | // 递归检查继承 |
||
583 | $func($extend); |
||
584 | |||
585 | // 取得block标签内容 |
||
586 | $blocks = array_merge($blocks, $this->parseBlock($template)); |
||
587 | |||
588 | return; |
||
589 | } |
||
590 | } else { |
||
591 | // 取得顶层模板block标签内容 |
||
592 | $baseBlocks = $this->parseBlock($template, true); |
||
593 | |||
594 | if (empty($extend)) { |
||
595 | // 无extend标签但有block标签的情况 |
||
596 | $extend = $template; |
||
597 | } |
||
598 | } |
||
599 | }; |
||
600 | |||
601 | $func($content); |
||
602 | |||
603 | if (!empty($extend)) { |
||
604 | if ($baseBlocks) { |
||
605 | $children = []; |
||
606 | foreach ($baseBlocks as $name => $val) { |
||
607 | $replace = $val['content']; |
||
608 | |||
609 | if (!empty($children[$name])) { |
||
610 | // 如果包含有子block标签 |
||
611 | foreach ($children[$name] as $key) { |
||
612 | $replace = str_replace($baseBlocks[$key]['begin'] . $baseBlocks[$key]['content'] . $baseBlocks[$key]['end'], $blocks[$key]['content'], $replace); |
||
613 | } |
||
614 | } |
||
615 | |||
616 | if (isset($blocks[$name])) { |
||
617 | // 带有{__block__}表示与所继承模板的相应标签合并,而不是覆盖 |
||
618 | $replace = str_replace(['{__BLOCK__}', '{__block__}'], $replace, $blocks[$name]['content']); |
||
619 | |||
620 | if (!empty($val['parent'])) { |
||
621 | // 如果不是最顶层的block标签 |
||
622 | $parent = $val['parent']; |
||
623 | |||
624 | if (isset($blocks[$parent])) { |
||
625 | $blocks[$parent]['content'] = str_replace($blocks[$name]['begin'] . $blocks[$name]['content'] . $blocks[$name]['end'], $replace, $blocks[$parent]['content']); |
||
626 | } |
||
627 | |||
628 | $blocks[$name]['content'] = $replace; |
||
629 | $children[$parent][] = $name; |
||
630 | |||
631 | continue; |
||
632 | } |
||
633 | } elseif (!empty($val['parent'])) { |
||
634 | // 如果子标签没有被继承则用原值 |
||
635 | $children[$val['parent']][] = $name; |
||
636 | $blocks[$name] = $val; |
||
637 | } |
||
638 | |||
639 | if (!$val['parent']) { |
||
640 | // 替换模板中的顶级block标签 |
||
641 | $extend = str_replace($val['begin'] . $val['content'] . $val['end'], $replace, $extend); |
||
642 | } |
||
643 | } |
||
644 | } |
||
645 | |||
646 | $content = $extend; |
||
647 | unset($blocks, $baseBlocks); |
||
648 | } |
||
649 | } |
||
650 | |||
651 | /** |
||
652 | * 替换页面中的literal标签 |
||
653 | * @access private |
||
654 | * @param string $content 模板内容 |
||
655 | * @param boolean $restore 是否为还原 |
||
656 | * @return void |
||
657 | */ |
||
658 | private function parseLiteral(&$content, $restore = false) |
||
659 | { |
||
660 | $regex = $this->getRegex($restore ? 'restoreliteral' : 'literal'); |
||
661 | |||
662 | if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { |
||
663 | if (!$restore) { |
||
664 | $count = count($this->literal); |
||
665 | |||
666 | // 替换literal标签 |
||
667 | foreach ($matches as $match) { |
||
668 | $this->literal[] = substr($match[0], strlen($match[1]), -strlen($match[2])); |
||
669 | $content = str_replace($match[0], "<!--###literal{$count}###-->", $content); |
||
670 | $count++; |
||
671 | } |
||
672 | } else { |
||
673 | // 还原literal标签 |
||
674 | foreach ($matches as $match) { |
||
675 | $content = str_replace($match[0], $this->literal[$match[1]], $content); |
||
676 | } |
||
677 | |||
678 | // 清空literal记录 |
||
679 | $this->literal = []; |
||
680 | } |
||
681 | |||
682 | unset($matches); |
||
683 | } |
||
684 | } |
||
685 | |||
686 | /** |
||
687 | * 获取模板中的block标签 |
||
688 | * @access private |
||
689 | * @param string $content 模板内容 |
||
690 | * @param boolean $sort 是否排序 |
||
691 | * @return array |
||
692 | */ |
||
693 | private function parseBlock(&$content, $sort = false) |
||
694 | { |
||
695 | $regex = $this->getRegex('block'); |
||
696 | $result = []; |
||
697 | |||
698 | if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE)) { |
||
699 | $right = $keys = []; |
||
700 | |||
701 | foreach ($matches as $match) { |
||
702 | if (empty($match['name'][0])) { |
||
703 | if (count($right) > 0) { |
||
704 | $tag = array_pop($right); |
||
705 | $start = $tag['offset'] + strlen($tag['tag']); |
||
706 | $length = $match[0][1] - $start; |
||
707 | |||
708 | $result[$tag['name']] = [ |
||
709 | 'begin' => $tag['tag'], |
||
710 | 'content' => substr($content, $start, $length), |
||
711 | 'end' => $match[0][0], |
||
712 | 'parent' => count($right) ? end($right)['name'] : '', |
||
713 | ]; |
||
714 | |||
715 | $keys[$tag['name']] = $match[0][1]; |
||
716 | } |
||
717 | } else { |
||
718 | // 标签头压入栈 |
||
719 | $right[] = [ |
||
720 | 'name' => $match[2][0], |
||
721 | 'offset' => $match[0][1], |
||
722 | 'tag' => $match[0][0], |
||
723 | ]; |
||
724 | } |
||
725 | } |
||
726 | |||
727 | unset($right, $matches); |
||
728 | |||
729 | if ($sort) { |
||
730 | // 按block标签结束符在模板中的位置排序 |
||
731 | array_multisort($keys, $result); |
||
732 | } |
||
733 | } |
||
734 | |||
735 | return $result; |
||
736 | } |
||
737 | |||
738 | /** |
||
739 | * 搜索模板页面中包含的TagLib库 |
||
740 | * 并返回列表 |
||
741 | * @access private |
||
742 | * @param string $content 模板内容 |
||
743 | * @return array|null |
||
744 | */ |
||
745 | private function getIncludeTagLib(&$content) |
||
746 | { |
||
747 | // 搜索是否有TagLib标签 |
||
748 | if (preg_match($this->getRegex('taglib'), $content, $matches)) { |
||
749 | // 替换TagLib标签 |
||
750 | $content = str_replace($matches[0], '', $content); |
||
751 | |||
752 | return explode(',', $matches['name']); |
||
753 | } |
||
754 | } |
||
755 | |||
756 | /** |
||
757 | * TagLib库解析 |
||
758 | * @access public |
||
759 | * @param string $tagLib 要解析的标签库 |
||
760 | * @param string $content 要解析的模板内容 |
||
761 | * @param boolean $hide 是否隐藏标签库前缀 |
||
762 | * @return void |
||
763 | */ |
||
764 | public function parseTagLib($tagLib, &$content, $hide = false) |
||
765 | { |
||
766 | if (false !== strpos($tagLib, '\\')) { |
||
767 | // 支持指定标签库的命名空间 |
||
768 | $className = $tagLib; |
||
769 | $tagLib = substr($tagLib, strrpos($tagLib, '\\') + 1); |
||
770 | } else { |
||
771 | $className = '\\think\\template\\taglib\\' . ucwords($tagLib); |
||
772 | } |
||
773 | |||
774 | $tLib = new $className($this); |
||
775 | |||
776 | $tLib->parseTag($content, $hide ? '' : $tagLib); |
||
777 | } |
||
778 | |||
779 | /** |
||
780 | * 分析标签属性 |
||
781 | * @access public |
||
782 | * @param string $str 属性字符串 |
||
783 | * @param string $name 不为空时返回指定的属性名 |
||
784 | * @return array |
||
785 | */ |
||
786 | public function parseAttr($str, $name = null) |
||
803 | } |
||
804 | |||
805 | /** |
||
806 | * 模板标签解析 |
||
807 | * 格式: {TagName:args [|content] } |
||
808 | * @access private |
||
809 | * @param string $content 要解析的模板内容 |
||
810 | * @return void |
||
811 | */ |
||
812 | private function parseTag(&$content) |
||
813 | { |
||
814 | $regex = $this->getRegex('tag'); |
||
815 | |||
816 | if (preg_match_all($regex, $content, $matches, PREG_SET_ORDER)) { |
||
817 | foreach ($matches as $match) { |
||
818 | $str = stripslashes($match[1]); |
||
819 | $flag = substr($str, 0, 1); |
||
820 | |||
821 | switch ($flag) { |
||
822 | case '$': |
||
1 ignored issue
–
show
|
|||
823 | // 解析模板变量 格式 {$varName} |
||
824 | // 是否带有?号 |
||
825 | if (false !== $pos = strpos($str, '?')) { |
||
1 ignored issue
–
show
|
|||
826 | $array = preg_split('/([!=]={1,2}|(?<!-)[><]={0,1})/', substr($str, 0, $pos), 2, PREG_SPLIT_DELIM_CAPTURE); |
||
827 | $name = $array[0]; |
||
828 | |||
829 | $this->parseVar($name); |
||
830 | //$this->parseVarFunction($name); |
||
831 | |||
832 | $str = trim(substr($str, $pos + 1)); |
||
833 | $this->parseVar($str); |
||
834 | $first = substr($str, 0, 1); |
||
835 | |||
836 | if (strpos($name, ')')) { |
||
1 ignored issue
–
show
|
|||
837 | // $name为对象或是自动识别,或者含有函数 |
||
838 | if (isset($array[1])) { |
||
1 ignored issue
–
show
|
|||
839 | $this->parseVar($array[2]); |
||
840 | $name .= $array[1] . $array[2]; |
||
841 | } |
||
1 ignored issue
–
show
|
|||
842 | |||
843 | switch ($first) { |
||
844 | case '?': |
||
1 ignored issue
–
show
|
|||
845 | $this->parseVarFunction($name); |
||
846 | $str = '<?php echo (' . $name . ') ? ' . $name . ' : ' . substr($str, 1) . '; ?>'; |
||
847 | break; |
||
848 | case '=': |
||
1 ignored issue
–
show
|
|||
849 | $str = '<?php if(' . $name . ') echo ' . substr($str, 1) . '; ?>'; |
||
850 | break; |
||
851 | default: |
||
1 ignored issue
–
show
|
|||
852 | $str = '<?php echo ' . $name . '?' . $str . '; ?>'; |
||
853 | } |
||
1 ignored issue
–
show
|
|||
854 | } else { |
||
1 ignored issue
–
show
|
|||
855 | if (isset($array[1])) { |
||
1 ignored issue
–
show
|
|||
856 | $express = true; |
||
857 | $this->parseVar($array[2]); |
||
858 | $express = $name . $array[1] . $array[2]; |
||
859 | } else { |
||
1 ignored issue
–
show
|
|||
860 | $express = false; |
||
861 | } |
||
1 ignored issue
–
show
|
|||
862 | |||
863 | if (in_array($first, ['?', '=', ':'])) { |
||
1 ignored issue
–
show
|
|||
864 | $str = trim(substr($str, 1)); |
||
865 | if ('$' == substr($str, 0, 1)) { |
||
1 ignored issue
–
show
|
|||
866 | $str = $this->parseVarFunction($str); |
||
867 | } |
||
1 ignored issue
–
show
|
|||
868 | } |
||
1 ignored issue
–
show
|
|||
869 | |||
870 | // $name为数组 |
||
871 | switch ($first) { |
||
872 | case '?': |
||
1 ignored issue
–
show
|
|||
873 | // {$varname??'xxx'} $varname有定义则输出$varname,否则输出xxx |
||
874 | $str = '<?php echo ' . ($express ?: 'isset(' . $name . ')') . ' ? ' . $this->parseVarFunction($name) . ' : ' . $str . '; ?>'; |
||
875 | break; |
||
876 | case '=': |
||
1 ignored issue
–
show
|
|||
877 | // {$varname?='xxx'} $varname为真时才输出xxx |
||
878 | $str = '<?php if(' . ($express ?: '!empty(' . $name . ')') . ') echo ' . $str . '; ?>'; |
||
879 | break; |
||
880 | case ':': |
||
1 ignored issue
–
show
|
|||
881 | // {$varname?:'xxx'} $varname为真时输出$varname,否则输出xxx |
||
882 | $str = '<?php echo ' . ($express ?: '!empty(' . $name . ')') . ' ? ' . $this->parseVarFunction($name) . ' : ' . $str . '; ?>'; |
||
883 | break; |
||
884 | default: |
||
1 ignored issue
–
show
|
|||
885 | if (strpos($str, ':')) { |
||
1 ignored issue
–
show
|
|||
886 | // {$varname ? 'a' : 'b'} $varname为真时输出a,否则输出b |
||
887 | $array = explode(':', $str, 2); |
||
888 | |||
889 | $array[0] = '$' == substr(trim($array[0]), 0, 1) ? $this->parseVarFunction($array[0]) : $array[0]; |
||
890 | $array[1] = '$' == substr(trim($array[1]), 0, 1) ? $this->parseVarFunction($array[1]) : $array[1]; |
||
891 | |||
892 | $str = implode(' : ', $array); |
||
893 | } |
||
1 ignored issue
–
show
|
|||
894 | $str = '<?php echo ' . ($express ?: '!empty(' . $name . ')') . ' ? ' . $str . '; ?>'; |
||
895 | } |
||
1 ignored issue
–
show
|
|||
896 | } |
||
1 ignored issue
–
show
|
|||
897 | } else { |
||
1 ignored issue
–
show
|
|||
898 | $this->parseVar($str); |
||
899 | $this->parseVarFunction($str); |
||
900 | $str = '<?php echo ' . $str . '; ?>'; |
||
901 | } |
||
1 ignored issue
–
show
|
|||
902 | break; |
||
903 | case ':': |
||
1 ignored issue
–
show
|
|||
904 | // 输出某个函数的结果 |
||
905 | $str = substr($str, 1); |
||
906 | $this->parseVar($str); |
||
907 | $str = '<?php echo ' . $str . '; ?>'; |
||
908 | break; |
||
909 | case '~': |
||
1 ignored issue
–
show
|
|||
910 | // 执行某个函数 |
||
911 | $str = substr($str, 1); |
||
912 | $this->parseVar($str); |
||
913 | $str = '<?php ' . $str . '; ?>'; |
||
914 | break; |
||
915 | case '-': |
||
1 ignored issue
–
show
|
|||
916 | case '+': |
||
1 ignored issue
–
show
|
|||
917 | // 输出计算 |
||
918 | $this->parseVar($str); |
||
919 | $str = '<?php echo ' . $str . '; ?>'; |
||
920 | break; |
||
921 | case '/': |
||
1 ignored issue
–
show
|
|||
922 | // 注释标签 |
||
923 | $flag2 = substr($str, 1, 1); |
||
924 | if ('/' == $flag2 || ('*' == $flag2 && substr(rtrim($str), -2) == '*/')) { |
||
1 ignored issue
–
show
|
|||
925 | $str = ''; |
||
926 | } |
||
1 ignored issue
–
show
|
|||
927 | break; |
||
928 | default: |
||
1 ignored issue
–
show
|
|||
929 | // 未识别的标签直接返回 |
||
930 | $str = $this->config['tpl_begin'] . $str . $this->config['tpl_end']; |
||
931 | break; |
||
932 | } |
||
933 | |||
934 | $content = str_replace($match[0], $str, $content); |
||
935 | } |
||
936 | |||
937 | unset($matches); |
||
938 | } |
||
939 | } |
||
940 | |||
941 | /** |
||
942 | * 模板变量解析,支持使用函数 |
||
943 | * 格式: {$varname|function1|function2=arg1,arg2} |
||
944 | * @access public |
||
945 | * @param string $varStr 变量数据 |
||
946 | * @return void |
||
947 | */ |
||
948 | public function parseVar(&$varStr) |
||
949 | { |
||
950 | $varStr = trim($varStr); |
||
951 | |||
952 | if (preg_match_all('/\$[a-zA-Z_](?>\w*)(?:[:\.][0-9a-zA-Z_](?>\w*))+/', $varStr, $matches, PREG_OFFSET_CAPTURE)) { |
||
953 | static $_varParseList = []; |
||
954 | |||
955 | while ($matches[0]) { |
||
956 | $match = array_pop($matches[0]); |
||
957 | |||
958 | //如果已经解析过该变量字串,则直接返回变量值 |
||
959 | if (isset($_varParseList[$match[0]])) { |
||
960 | $parseStr = $_varParseList[$match[0]]; |
||
961 | } else { |
||
962 | if (strpos($match[0], '.')) { |
||
963 | $vars = explode('.', $match[0]); |
||
964 | $first = array_shift($vars); |
||
965 | |||
966 | if ('$Think' == $first) { |
||
967 | // 所有以Think.打头的以特殊变量对待 无需模板赋值就可以输出 |
||
968 | $parseStr = $this->parseThinkVar($vars); |
||
969 | } elseif ('$Request' == $first) { |
||
970 | // 获取Request请求对象参数 |
||
971 | $method = array_shift($vars); |
||
972 | if (!empty($vars)) { |
||
973 | $params = implode('.', $vars); |
||
974 | if ('true' != $params) { |
||
975 | $params = '\'' . $params . '\''; |
||
976 | } |
||
977 | } else { |
||
978 | $params = ''; |
||
979 | } |
||
980 | |||
981 | $parseStr = 'app(\'request\')->' . $method . '(' . $params . ')'; |
||
982 | } else { |
||
983 | switch ($this->config['tpl_var_identify']) { |
||
984 | case 'array': // 识别为数组 |
||
1 ignored issue
–
show
|
|||
985 | $parseStr = $first . '[\'' . implode('\'][\'', $vars) . '\']'; |
||
986 | break; |
||
987 | case 'obj': // 识别为对象 |
||
1 ignored issue
–
show
|
|||
988 | $parseStr = $first . '->' . implode('->', $vars); |
||
989 | break; |
||
990 | default: // 自动判断数组或对象 |
||
1 ignored issue
–
show
|
|||
991 | $parseStr = '(is_array(' . $first . ')?' . $first . '[\'' . implode('\'][\'', $vars) . '\']:' . $first . '->' . implode('->', $vars) . ')'; |
||
992 | } |
||
993 | } |
||
994 | } else { |
||
995 | $parseStr = str_replace(':', '->', $match[0]); |
||
996 | } |
||
997 | |||
998 | $_varParseList[$match[0]] = $parseStr; |
||
999 | } |
||
1000 | |||
1001 | $varStr = substr_replace($varStr, $parseStr, $match[1], strlen($match[0])); |
||
1002 | } |
||
1003 | unset($matches); |
||
1004 | } |
||
1005 | } |
||
1006 | |||
1007 | /** |
||
1008 | * 对模板中使用了函数的变量进行解析 |
||
1009 | * 格式 {$varname|function1|function2=arg1,arg2} |
||
1010 | * @access public |
||
1011 | * @param string $varStr 变量字符串 |
||
1012 | * @param bool $autoescape 自动转义 |
||
1013 | * @return void |
||
1014 | */ |
||
1015 | public function parseVarFunction(&$varStr, $autoescape = true) |
||
1016 | { |
||
1017 | if (!$autoescape && false === strpos($varStr, '|')) { |
||
1018 | return $varStr; |
||
1019 | } elseif ($autoescape && !preg_match('/\|(\s)?raw(\||\s)?/i', $varStr)) { |
||
1020 | $varStr .= '|' . $this->config['default_filter']; |
||
1021 | } |
||
1022 | |||
1023 | static $_varFunctionList = []; |
||
1024 | |||
1025 | $_key = md5($varStr); |
||
1026 | |||
1027 | //如果已经解析过该变量字串,则直接返回变量值 |
||
1028 | if (isset($_varFunctionList[$_key])) { |
||
1029 | $varStr = $_varFunctionList[$_key]; |
||
1030 | } else { |
||
1031 | $varArray = explode('|', $varStr); |
||
1032 | |||
1033 | // 取得变量名称 |
||
1034 | $name = trim(array_shift($varArray)); |
||
1035 | |||
1036 | // 对变量使用函数 |
||
1037 | $length = count($varArray); |
||
1038 | |||
1039 | // 取得模板禁止使用函数列表 |
||
1040 | $template_deny_funs = explode(',', $this->config['tpl_deny_func_list']); |
||
1041 | |||
1042 | for ($i = 0; $i < $length; $i++) { |
||
1043 | $args = explode('=', $varArray[$i], 2); |
||
1044 | |||
1045 | // 模板函数过滤 |
||
1046 | $fun = trim($args[0]); |
||
1047 | if (in_array($fun, $template_deny_funs)) { |
||
1048 | continue; |
||
1049 | } |
||
1050 | |||
1051 | switch (strtolower($fun)) { |
||
1052 | case 'raw': |
||
1 ignored issue
–
show
|
|||
1053 | break; |
||
1054 | case 'date': |
||
1 ignored issue
–
show
|
|||
1055 | $name = 'date(' . $args[1] . ',!is_numeric(' . $name . ')? strtotime(' . $name . ') : ' . $name . ')'; |
||
1056 | break; |
||
1057 | case 'first': |
||
1 ignored issue
–
show
|
|||
1058 | $name = 'current(' . $name . ')'; |
||
1059 | break; |
||
1060 | case 'last': |
||
1 ignored issue
–
show
|
|||
1061 | $name = 'end(' . $name . ')'; |
||
1062 | break; |
||
1063 | case 'upper': |
||
1 ignored issue
–
show
|
|||
1064 | $name = 'strtoupper(' . $name . ')'; |
||
1065 | break; |
||
1066 | case 'lower': |
||
1 ignored issue
–
show
|
|||
1067 | $name = 'strtolower(' . $name . ')'; |
||
1068 | break; |
||
1069 | case 'format': |
||
1 ignored issue
–
show
|
|||
1070 | $name = 'sprintf(' . $args[1] . ',' . $name . ')'; |
||
1071 | break; |
||
1072 | case 'default': // 特殊模板函数 |
||
1 ignored issue
–
show
|
|||
1073 | if (false === strpos($name, '(')) { |
||
1 ignored issue
–
show
|
|||
1074 | $name = '(isset(' . $name . ') && (' . $name . ' !== \'\')?' . $name . ':' . $args[1] . ')'; |
||
1075 | } else { |
||
1 ignored issue
–
show
|
|||
1076 | $name = '(' . $name . ' ?: ' . $args[1] . ')'; |
||
1077 | } |
||
1 ignored issue
–
show
|
|||
1078 | break; |
||
1079 | default: // 通用模板函数 |
||
1 ignored issue
–
show
|
|||
1080 | if (isset($args[1])) { |
||
1 ignored issue
–
show
|
|||
1081 | if (strstr($args[1], '###')) { |
||
1 ignored issue
–
show
|
|||
1082 | $args[1] = str_replace('###', $name, $args[1]); |
||
1083 | $name = "$fun($args[1])"; |
||
1084 | } else { |
||
1 ignored issue
–
show
|
|||
1085 | $name = "$fun($name,$args[1])"; |
||
1086 | } |
||
1 ignored issue
–
show
|
|||
1087 | } else { |
||
1 ignored issue
–
show
|
|||
1088 | if (!empty($args[0])) { |
||
1 ignored issue
–
show
|
|||
1089 | $name = "$fun($name)"; |
||
1090 | } |
||
1 ignored issue
–
show
|
|||
1091 | } |
||
1 ignored issue
–
show
|
|||
1092 | } |
||
1093 | } |
||
1094 | |||
1095 | $_varFunctionList[$_key] = $name; |
||
1096 | $varStr = $name; |
||
1097 | } |
||
1098 | return $varStr; |
||
1099 | } |
||
1100 | |||
1101 | /** |
||
1102 | * 特殊模板变量解析 |
||
1103 | * 格式 以 $Think. 打头的变量属于特殊模板变量 |
||
1104 | * @access public |
||
1105 | * @param array $vars 变量数组 |
||
1106 | * @return string |
||
1107 | */ |
||
1108 | public function parseThinkVar($vars) |
||
1109 | { |
||
1110 | $type = strtoupper(trim(array_shift($vars))); |
||
1111 | $param = implode('.', $vars); |
||
1112 | |||
1113 | if ($vars) { |
||
1114 | switch ($type) { |
||
1115 | case 'SERVER': |
||
1 ignored issue
–
show
|
|||
1116 | $parseStr = 'app(\'request\')->server(\'' . $param . '\')'; |
||
1117 | break; |
||
1118 | case 'GET': |
||
1 ignored issue
–
show
|
|||
1119 | $parseStr = 'app(\'request\')->get(\'' . $param . '\')'; |
||
1120 | break; |
||
1121 | case 'POST': |
||
1 ignored issue
–
show
|
|||
1122 | $parseStr = 'app(\'request\')->post(\'' . $param . '\')'; |
||
1123 | break; |
||
1124 | case 'COOKIE': |
||
1 ignored issue
–
show
|
|||
1125 | $parseStr = 'app(\'cookie\')->get(\'' . $param . '\')'; |
||
1126 | break; |
||
1127 | case 'SESSION': |
||
1 ignored issue
–
show
|
|||
1128 | $parseStr = 'app(\'session\')->get(\'' . $param . '\')'; |
||
1129 | break; |
||
1130 | case 'ENV': |
||
1 ignored issue
–
show
|
|||
1131 | $parseStr = 'app(\'request\')->env(\'' . $param . '\')'; |
||
1132 | break; |
||
1133 | case 'REQUEST': |
||
1 ignored issue
–
show
|
|||
1134 | $parseStr = 'app(\'request\')->request(\'' . $param . '\')'; |
||
1135 | break; |
||
1136 | case 'CONST': |
||
1 ignored issue
–
show
|
|||
1137 | $parseStr = strtoupper($param); |
||
1138 | break; |
||
1139 | case 'LANG': |
||
1 ignored issue
–
show
|
|||
1140 | $parseStr = 'app(\'lang\')->get(\'' . $param . '\')'; |
||
1141 | break; |
||
1142 | case 'CONFIG': |
||
1 ignored issue
–
show
|
|||
1143 | $parseStr = 'app(\'config\')->get(\'' . $param . '\')'; |
||
1144 | break; |
||
1145 | default: |
||
1 ignored issue
–
show
|
|||
1146 | $parseStr = '\'\''; |
||
1147 | break; |
||
1148 | } |
||
1149 | } else { |
||
1150 | switch ($type) { |
||
1151 | case 'NOW': |
||
1 ignored issue
–
show
|
|||
1152 | $parseStr = "date('Y-m-d g:i a',time())"; |
||
1153 | break; |
||
1154 | case 'VERSION': |
||
1 ignored issue
–
show
|
|||
1155 | $parseStr = 'app()->version()'; |
||
1156 | break; |
||
1157 | case 'LDELIM': |
||
1 ignored issue
–
show
|
|||
1158 | $parseStr = '\'' . ltrim($this->config['tpl_begin'], '\\') . '\''; |
||
1159 | break; |
||
1160 | case 'RDELIM': |
||
1 ignored issue
–
show
|
|||
1161 | $parseStr = '\'' . ltrim($this->config['tpl_end'], '\\') . '\''; |
||
1162 | break; |
||
1163 | default: |
||
1 ignored issue
–
show
|
|||
1164 | if (defined($type)) { |
||
1 ignored issue
–
show
|
|||
1165 | $parseStr = $type; |
||
1166 | } else { |
||
1 ignored issue
–
show
|
|||
1167 | $parseStr = ''; |
||
1168 | } |
||
1 ignored issue
–
show
|
|||
1169 | } |
||
1170 | } |
||
1171 | |||
1172 | return $parseStr; |
||
1173 | } |
||
1174 | |||
1175 | /** |
||
1176 | * 分析加载的模板文件并读取内容 支持多个模板文件读取 |
||
1177 | * @access private |
||
1178 | * @param string $templateName 模板文件名 |
||
1179 | * @return string |
||
1180 | */ |
||
1181 | private function parseTemplateName($templateName) |
||
1182 | { |
||
1183 | $array = explode(',', $templateName); |
||
1184 | $parseStr = ''; |
||
1185 | |||
1186 | foreach ($array as $templateName) { |
||
1187 | if (empty($templateName)) { |
||
1188 | continue; |
||
1189 | } |
||
1190 | |||
1191 | if (0 === strpos($templateName, '$')) { |
||
1192 | //支持加载变量文件名 |
||
1193 | $templateName = $this->get(substr($templateName, 1)); |
||
1194 | } |
||
1195 | |||
1196 | $template = $this->parseTemplateFile($templateName); |
||
1197 | |||
1198 | if ($template) { |
||
1199 | // 获取模板文件内容 |
||
1200 | $parseStr .= file_get_contents($template); |
||
1201 | } |
||
1202 | } |
||
1203 | |||
1204 | return $parseStr; |
||
1205 | } |
||
1206 | |||
1207 | /** |
||
1208 | * 解析模板文件名 |
||
1209 | * @access private |
||
1210 | * @param string $template 文件名 |
||
1211 | * @return string|false |
||
1212 | */ |
||
1213 | private function parseTemplateFile($template) |
||
1244 | } |
||
1245 | |||
1246 | /** |
||
1247 | * 按标签生成正则 |
||
1248 | * @access private |
||
1249 | * @param string $tagName 标签名 |
||
1250 | * @return string |
||
1251 | */ |
||
1252 | private function getRegex($tagName) |
||
1309 | } |
||
1310 | |||
1311 | public function __debugInfo() |
||
1317 | } |
||
1318 | } |
||
1319 |