Discuz!源代码分析系列(4)--./include/template.func.php(模板)

Section One--./include/global.func.php---->template function
  1. function template($file, $templateid = 0, $tpldir = '') {
  2.         global $tplrefresh;

  3.         $tpldir = $tpldir ? $tpldir : TPLDIR;
  4.         $templateid = $templateid ? $templateid : TEMPLATEID;

  5.         $tplfile = DISCUZ_ROOT.'./'.$tpldir.'/'.$file.'.htm';
  6.         $objfile = DISCUZ_ROOT.'./forumdata/templates/'.$templateid.'_'.$file.'.tpl.php';
  7.         if(TEMPLATEID != 1 && $templateid != 1 && !file_exists($tplfile)) {
  8.                 return template($file, 1, './templates/default/');
  9.         }
  10.         if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {
  11.                 if(@filemtime($tplfile) > @filemtime($objfile)) {
  12.                         require_once DISCUZ_ROOT.'./include/template.func.php';
  13.                         parse_template($file, $templateid, $tpldir);
  14.                 }
  15.         }
  16.         return $objfile;
  17. }
复制代码


这个函数一共有三个传入参数:
$file 表示模板名
$templateid 表示模板id
$tpldir 表示模板目录
  1. global $tplrefresh;
复制代码

这个是把$tplrefresh作为一个全局变量,tplrefresh表示是不是刷新模板

  1.         $tpldir = $tpldir ? $tpldir : TPLDIR;
  2.         $templateid = $templateid ? $templateid : TEMPLATEID;
复制代码

给$tpldir和$templateid赋值,如果没有传进来就用常量TPLDIR和TEMPLATEID给它们值

  1.         $tplfile = DISCUZ_ROOT.'./'.$tpldir.'/'.$file.'.htm';
  2.         $objfile = DISCUZ_ROOT.'./forumdata/templates/'.$templateid.'_'.$file.'.tpl.php';
复制代码

这里是把$tplfile(表示的是模板文件)和$objfile(表示的是要编译成的文件)赋值

  1.         if(TEMPLATEID != 1 && $templateid != 1 && !file_exists($tplfile)) {
  2.                 return template($file, 1, './templates/default/');
  3.         }
复制代码

防止TEMPLATEID不等于1且$templateid不等于1,而且模板文件不存在导致空白问题。
这里也可以算一个迭代,也可以不算,就是把1作为第二个参数再调用函数本身。

  1.         if($tplrefresh == 1 || ($tplrefresh > 1 && substr($GLOBALS['timestamp'], -1) > $tplrefresh)) {
  2.                 if(@filemtime($tplfile) > @filemtime($objfile)) {
  3.                         require_once DISCUZ_ROOT.'./include/template.func.php';
  4.                         parse_template($file, $templateid, $tpldir);
  5.                 }
  6.         }
  7.         return $objfile;
复制代码

很巧妙的一段,Discuz的模板缓存就体现在这里,如果你没打开模板刷新的话(config.inc.php->$tplrefresh=0), 这里就直接返回一个$objfile了,而这个文件是你第一次建论坛的时候就写入的,如果你不改模板的话,关了是能提高相当一部分效率的!反之,如果你打 开了模板刷新的话就接着判断是不是模板文件的建立时间大于forumdata/templates下的文件,是的话就引用./include /template.func.php写入模板文件到forumdata/templates中,否则的话还是直接返回一个已经编译好的模板文件。


 

 

 

  1. //防止非法引用
  2. if(!defined('IN_DISCUZ')) {
  3.         exit('Access Denied');
  4. }
复制代码

  1. /**
  2. * 这个是关键模板解析函数,通过正则表达式来替换掉模板中的相关语句,使之变成标准的php语句,写入缓存(./forumdata/template),从而include到页面中显示出来
  3. * @para string $file //解析的模板名,只要文件名就可以了,会自动加上htm,如果有缓存的话就变成"模板id_文件名.tpl.php"
  4. * @para int $templateid //模板的id
  5. * @para string $tpldir //模板所在的目录
  6. *
  7. */

  8. function parse_template($file, $templateid, $tpldir) {
  9.         global $language;

  10.         $nest = 5;
  11.         $tplfile = DISCUZ_ROOT."./$tpldir/$file.htm";
  12.         $objfile = DISCUZ_ROOT."./forumdata/templates/{$templateid}_$file.tpl.php";

  13.         if(!@$fp = fopen($tplfile, 'r')) {
  14.                 dexit("Current template file './$tpldir/$file.htm' not found or have no access!");
  15.         } elseif(!include_once language('templates', $templateid, $tpldir)) {
  16.                 dexit("<br>Current template pack do not have a necessary language file 'templates.lang.php' or have syntax error!");
  17.         }

  18.         $template = fread($fp, filesize($tplfile));
  19.         fclose($fp);

  20.         $var_regexp = "((\\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)(\[[a-zA-Z0-9_\-\.\"\'\[\]\$\x7f-\xff]+\])*)";
  21.         $const_regexp = "([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)";

  22.         $template = preg_replace("/([\n\r]+)\t+/s", "\\1", $template);
  23.         $template = preg_replace("/\<\!\-\-\{(.+?)\}\-\-\>/s", "{\\1}", $template);
  24.         $template = preg_replace("/\{lang\s+(.+?)\}/ies", "languagevar('\\1')", $template);
  25.         $template = preg_replace("/\{faq\s+(.+?)\}/ies", "faqvar('\\1')", $template);
  26.         $template = str_replace("{LF}", "<?=\"\\n\"?>", $template);

  27.         $template = preg_replace("/\{(\\\$[a-zA-Z0-9_\[\]\'\"\$\.\x7f-\xff]+)\}/s", "<?=\\1?>", $template);
  28.         $template = preg_replace("/$var_regexp/es", "addquote('<?=\\1?>')", $template);
  29.         $template = preg_replace("/\<\?\=\<\?\=$var_regexp\?\>\?\>/es", "addquote('<?=\\1?>')", $template);

  30.         $template = "<? if(!defined('IN_DISCUZ')) exit('Access Denied'); ?>\n$template";
  31.         $template = preg_replace("/[\n\r\t]*\{template\s+([a-z0-9_]+)\}[\n\r\t]*/is", "\n<? include template('\\1'); ?>\n", $template);
  32.         $template = preg_replace("/[\n\r\t]*\{template\s+(.+?)\}[\n\r\t]*/is", "\n<? include template(\\1); ?>\n", $template);
  33.         $template = preg_replace("/[\n\r\t]*\{eval\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? \\1 ?>\n','')", $template);
  34.         $template = preg_replace("/[\n\r\t]*\{echo\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? echo \\1; ?>\n','')", $template);
  35.         $template = preg_replace("/[\n\r\t]*\{elseif\s+(.+?)\}[\n\r\t]*/ies", "stripvtags('\n<? } elseif(\\1) { ?>\n','')", $template);
  36.         $template = preg_replace("/[\n\r\t]*\{else\}[\n\r\t]*/is", "\n<? } else { ?>\n", $template);

  37.         for($i = 0; $i < $nest; $i++) {
  38.                 $template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\}[\n\r]*(.+?)[\n\r]*\{\/loop\}[\n\r\t]*/ies", "stripvtags('\n<? if(is_array(\\1)) { foreach(\\1 as \\2) { ?>','\n\\3\n<? } } ?>\n')", $template);
  39.                 $template = preg_replace("/[\n\r\t]*\{loop\s+(\S+)\s+(\S+)\s+(\S+)\}[\n\r\t]*(.+?)[\n\r\t]*\{\/loop\}[\n\r\t]*/ies", "stripvtags('\n<? if(is_array(\\1)) { foreach(\\1 as \\2 => \\3) { ?>','\n\\4\n<? } } ?>\n')", $template);
  40.                 $template = preg_replace("/[\n\r\t]*\{if\s+(.+?)\}[\n\r]*(.+?)[\n\r]*\{\/if\}[\n\r\t]*/ies", "stripvtags('\n<? if(\\1) { ?>','\n\\2\n<? } ?>\n')", $template);
  41.         }

  42.         $template = preg_replace("/\{$const_regexp\}/s", "<?=\\1?>", $template);
  43.         $template = preg_replace("/ \?\>[\n\r]*\<\? /s", " ", $template);

  44.         if(!@$fp = fopen($objfile, 'w')) {
  45.                 dexit("Directory './forumdata/templates/' not found or have no access!");
  46.         }

  47.         $template = preg_replace("/\"(http)?[\w\.\/:]+\?[^\"]+?&[^\"]+?\"/e", "transamp('\\0')", $template);
  48.         $template = preg_replace("/\<script[^\>]*?src=\"(.+?)\".*?\>\s*\<\/script\>/ise", "stripscriptamp('\\1')", $template);

  49.         flock($fp, 2);
  50.         fwrite($fp, $template);
  51.         fclose($fp);
  52. }
复制代码

  1. /**
  2. * 几个替换,过滤掉一些东西
  3. * @para string $str
  4. *
  5. * @return string
  6. */
  7.        
  8. function transamp($str) {
  9.         $str = str_replace('&', '&', $str);
  10.         $str = str_replace('&', '&', $str);
  11.         $str = str_replace('\"', '"', $str);
  12.         return $str;
  13. }
复制代码

  1. /**
  2. * 从正则表达式来看是给ubb代码去掉一个\符号的,应该是为安全性着想的
  3. * @para string $val
  4. *
  5. * @return string
  6. */

  7. function addquote($var) {
  8.         return str_replace("\\\"", "\"", preg_replace("/\[([a-zA-Z0-9_\-\.\x7f-\xff]+)\]/s", "['\\1']", $var));
  9. }
复制代码

  1. /**
  2. * 把一个字符用语言包中的来替换,没有找到的话就用!string来替换
  3. * @para string $val
  4. *
  5. * @return string
  6. */

  7. function languagevar($var) {
  8.         if(isset($GLOBALS['language'][$var])) {
  9.                 return $GLOBALS['language'][$var];
  10.         } else {
  11.                 return "!$var!";
  12.         }
  13. }
复制代码

       
  1. /**
  2. * FAQ中把id和关建字用一个有效的链接来替换
  3. * @para array $val
  4. *
  5. * @return string
  6. */

  7. function faqvar($var) {
  8.         global $_DCACHE;
  9.         include_once DISCUZ_ROOT.'./forumdata/cache/cache_faqs.php';

  10.         if(isset($_DCACHE['faqs'][$var])) {
  11.                 return '<a href="faq.php?action=message&id='.$_DCACHE['faqs'][$var]['id'].'" target="_blank">'.$_DCACHE['faqs'][$var]['keyword'].'</a>';
  12.         } else {
  13.                 return "!$var!";
  14.         }
  15. }
复制代码

  1. /**
  2. * 去掉自定义的一些tag
  3. * @para string $expr
  4. * @para string $statement
  5. * @return string
  6. */

  7. function stripvtags($expr, $statement) {
  8.         $expr = str_replace("\\\"", "\"", preg_replace("/\<\?\=(\\\$.+?)\?\>/s", "\\1", $expr));
  9.         $statement = str_replace("\\\"", "\"", $statement);
  10.         return $expr.$statement;
  11. }
复制代码
  1. /**
  2. * 作用是把&符号的html编码形式换成&,然后换成javascript引用的形式。
  3. * @para string $s
  4. *
  5. * @return string
  6. */

  7. function stripscriptamp($s) {
  8.         $s = str_replace('&', '&', $s);
  9.         return "<script src=\"$s\" type=\"text/javascript\"></script>";
  10. }
复制代码
 

posted on 2009-11-27 13:52  14的路  阅读(1502)  评论(0编辑  收藏  举报

导航

友情链接:源码下载