Discuz开发 Discuz 模版解析代码剥离

[复制链接]
建站高手 发表于 2015-7-31 16:45:48 [Discuz开发] 显示全部楼层 |阅读模式 上一主题 下一主题

马上注册,一起探讨正确快速的建站方法

您需要 登录 才可以下载或查看,没有帐号?快速注册

x
虽说discuz的毛病居多,但是有些东西还是值得赞扬的。比如说模版解析那套代码,检测到修改过模版后,程序会再次生成此文件包含的所有文件的缓存。Discuz的模板解析原理是用正则表达式替换一些模板中的规定的语言标记,然后写到cache目录中,再用include引用到index, forumdisplay等等中,和smarty的原理基本上相同,但是没有smarty强大的功能。但是呢,我们做的是一个小小的网站,用不着去用smarty这样大型的模版框架,维护起来还很麻烦,而且,你不觉得每次都要赋值和display页面很烦么。。

我看了一下网上有人提取过出来,但是版本都已经是很老的了,所以就想在新版本把模版解析的代码剥离开来。

  1. function checktplrefresh($maintpl, $subtpl, $timecompare, $cachefile, $tpldir, $file) {
  2.         if(empty($timecompare) || filemtime($subtpl) > $timecompare) {
  3.             $this->template = new template();
  4.             $this->template->parse_template($maintpl, 0, $tpldir, $file, $cachefile);
  5.             unset($maintpl, $subtpl, $timecompare, $cachefile, $tpldir, $file);
  6.             return TRUE;
  7.         }
  8.         return FALSE;
  9.     }

  10.     function display($file) {
  11.         $oldfile    = $file;
  12.         $tpldir     = TPL.THEME.'/';
  13.         $filebak    = $file;
  14.         if(!$tpldir) {
  15.             $tpldir = TPL.THEME.'/';
  16.         }
  17.         $tplfile    = $tpldir.$file.'.php';
  18.         $cachefile  = TPL_CACHE.str_replace('/', '_', THEME.'/'.$file).'.tpl.php';
  19.         if(file_exists($cachefile)) {
  20.             $timecompare = filemtime($cachefile);
  21.         } else {
  22.             $timecompare = NULL;
  23.         }
  24.         $this->checktplrefresh($tplfile, $tplfile, $timecompare, $cachefile, $tpldir, $file);
  25.         unset($oldfile, $filebak, $tplfile, $tplfile, $timecompare, $tpldir, $file);
  26.         return $cachefile;
  27.     }
复制代码


在上面的代码中,TPL和THEME为分别为你的模版路径和主题名称,你可以写在你的全局设置中,要注意的是,这里的模版路径为.tpl.php,如果你想要以html结尾,你可以自己修改这里。

下面就是模版的类了。在这里,使用了正则表达式来替换特定的代码串。

  1. <?php
  2. (!defined('INAPP') || INAPP !== TRUE) && die('Access deny.');

  3. class template {

  4.     private $subtemplates = array();
  5.     private $replacecode = array('search' => array(), 'replace' => array());
  6.     private $language = array();
  7.     private $file = '';

  8.     public function parse_template($tplfile, $templateid, $tpldir, $file, $cachefile) {
  9.         $this->file = $file;

  10.         if($fp = fopen($tplfile, 'r')) {
  11.             $template = fread($fp, filesize($tplfile));
  12.             fclose($fp);
  13.         } else {
  14.             $this->error('template_notfound', $tplfile);
  15.         }

  16.         $var_regexp = "(($[a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*(->)?[a-zA-Z0-9_x7f-xff]*)([[a-zA-Z0-9_-."'[]$x7f-xff]+])*)";
  17.         $const_regexp = "([a-zA-Z_x7f-xff][a-zA-Z0-9_x7f-xff]*)";

  18.         $headerexists = preg_match("/{(sub)?templates+[w/]+?header}/", $template);

  19.         $template = str_ireplace("", '', $template);
  20.         $template = preg_replace("/([nr]+)t+/s", "1", $template);
  21.         $template = preg_replace("/{C}/s", "{1}", $template);
  22.         $template = preg_replace("/{langs+(.+?)}/ies", "$this->languagevar('1')", $template);
  23.         $template = preg_replace("/[nrt]*{ad/(.+?)}[nrt]*/ie", "$this->adtags('1')", $template);
  24.         $template = preg_replace("/[nrt]*{ads+([a-zA-Z0-9_[]]+)/(.+?)}[nrt]*/ie", "$this->adtags('2', '1')", $template);
  25.         $template = preg_replace("/[nrt]*{date((.+?))}[nrt]*/ie", "$this->datetags('1')", $template);

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

  30.         $template = preg_replace("/[nrt]*{templates+([a-z0-9_:/]+)}[nrt]*/ies", "$this->stripvtags('')", $template);
  31.         $template = preg_replace("/[nrt]*{templates+(.+?)}[nrt]*/ies", "$this->stripvtags('')", $template);
  32.         $template = preg_replace("/[nrt]*{echos+(.+?)}[nrt]*/ies", "$this->stripvtags('')", $template);

  33.         $template = preg_replace("/([nrt]*){ifs+(.+?)}([nrt]*)/ies", "$this->stripvtags('13')", $template);
  34.         $template = preg_replace("/([nrt]*){elseifs+(.+?)}([nrt]*)/ies", "$this->stripvtags('13')", $template);
  35.         $template = preg_replace("/{else}/i", "", $template);
  36.         $template = preg_replace("/{/if}/i", "", $template);

  37.         $template = preg_replace("/[nrt]*{loops+(S+)s+(S+)}[nrt]*/ies", "$this->stripvtags('')", $template);
  38.         $template = preg_replace("/[nrt]*{loops+(S+)s+(S+)s+(S+)}[nrt]*/ies", "$this->stripvtags(' 3) { ?>')", $template);
  39.         $template = preg_replace("/{/loop}/i", "", $template);

  40.         $template = preg_replace("/{$const_regexp}/s", "", $template);
  41.         if(!empty($this->replacecode)) {
  42.             $template = str_replace($this->replacecode['search'], $this->replacecode['replace'], $template);
  43.         }
  44.         $template = preg_replace("/ ?>[nr]*transamp('')", $template);
  45.         $template = preg_replace("/]*?src="(.+?)"(.*?)>s*/ies", "$this->stripscriptamp('1', '2')", $template);
  46.         $template = preg_replace("//is", "", $template);

  47.         $headeradd = '';
  48.         $this->subtemplates = array();
  49.         for($i = 1; $i <= 3; $i++) {
  50.             if($this->strexists($template, '{subtemplate')) {
  51.                 $template = preg_replace("/[nrt]*({C})?[nrt]*/ies", "$this->loadsubtemplate('2')", $template);
  52.             }
  53.         }
  54.         if(!empty($this->subtemplates)) {
  55.             $headeradd .= "n0n";
  56.             foreach($this->subtemplates as $fname) {
  57.                 $headeradd .= '|| $this->checktplrefresh("'.$tplfile.'", "'.$fname.'", '.time().', "'.$cachefile.'", "'.$tpldir.'", "'.$file.'")'."n";
  58.             }
  59.             $headeradd .= ';';
  60.         }
  61.         $template = "n$template";

  62.         if(!$fp = fopen($cachefile, 'w')) {
  63.             $this->error('directory_notfound', dirname($cachefile));
  64.         }
  65.         flock($fp, 2);
  66.         fwrite($fp, $template);
  67.         fclose($fp);
  68.     }

  69.     private function languagevar($var) {
  70.         if(isset($langvar[$var])) {
  71.             return $langvar[$var];
  72.         } else {
  73.             return '!'.$var.'!';
  74.         }
  75.     }

  76.     private function adtags($parameter, $varname = '') {
  77.         $parameter = stripslashes($parameter);
  78.         $i = count($this->replacecode['search']);
  79.         $this->replacecode['search'][$i] = $search = "{C}";
  80.         $this->replacecode['replace'][$i] = "";
  81.         return $search;
  82.     }

  83.     private function datetags($parameter) {
  84.         $parameter = stripslashes($parameter);
  85.         $i = count($this->replacecode['search']);
  86.         $this->replacecode['search'][$i] = $search = "{C}";
  87.         $this->replacecode['replace'][$i] = "";
  88.         return $search;
  89.     }

  90.     private function stripphpcode($type, $code) {
  91.         $this->phpcode[$type][] = $code;
  92.         return '{phpcode:'.$type.'/'.(count($this->phpcode[$type]) - 1).'}';
  93.     }

  94.     private function loadsubtemplate($file) {
  95.         $tplfile = $this->display($file, 0, '', 1);
  96.         $filename = $tplfile;
  97.         if(($content = implode('', file($filename))) || ($content = $this->getphptemplate(implode('', file(substr($filename, 0, -4).'.php'))))) {
  98.             $this->subtemplates[] = $tplfile;
  99.             return $content;
  100.         } else {
  101.             return '';
  102.         }
  103.     }

  104.     private function getphptemplate($content) {
  105.         $pos = strpos($content, "n");
  106.         return $pos !== false ? substr($content, $pos + 1) : $content;
  107.     }

  108.     private function transamp($str) {
  109.         $str = str_replace('&', '&', $str);
  110.         $str = str_replace('&amp;', '&', $str);
  111.         $str = str_replace('"', '"', $str);
  112.         return $str;
  113.     }

  114.     private function addquote($var) {
  115.         return str_replace(""", """, preg_replace("/[([a-zA-Z0-9_-.x7f-xff]+)]/s", "['1']", $var));
  116.     }


  117.     private function stripvtags($expr, $statement = '') {
  118.         $expr = str_replace(""", """, preg_replace("//s", "1", $expr));
  119.         $statement = str_replace(""", """, $statement);
  120.         return $expr.$statement;
  121.     }

  122.     private function stripscriptamp($s, $extra) {
  123.         $extra = str_replace('"', '"', $extra);
  124.         $s = str_replace('&', '&', $s);
  125.         return "";
  126.     }

  127.     private function strexists($string, $find) {
  128.         return !(strpos($string, $find) === FALSE);
  129.     }

  130.     private function error($message, $tplname) {
  131.         exit($message);
  132.     }
  133. }
复制代码

以上代码已经能正常使用,模版的话,请参考一下discuz的模版的写法。都是一样的。

不过要注意的是,我去掉了一些比如钩子、diy相关的东西。这些东西一般都不会用得到,所以代码的量就减少了很多。

剩下的,就自己组织把。记得cache目录需要写入权限~~




上一篇:让Discuz X2 支持@通知功能
下一篇:QQ互联官方接口升级oAuth2 模式导致登录失败解决方法

大神点评5

百家乐园 发表于 2015-7-31 16:54:07 [Discuz开发] 显示全部楼层
这个需要请技术才可以的吧
www.bjly.cc百乐园论
1547909727 发表于 2015-8-1 09:53:49 [Discuz开发] 显示全部楼层
很给力,希望分享更多给力的帖子啊。
zkqh 发表于 2015-8-2 10:01:36 [Discuz开发] 显示全部楼层
非常不错的文章  www.zkqh.net
福州墙绘www.zkqh.net
djy00123 发表于 2015-8-3 00:31:24 [Discuz开发] 显示全部楼层
强烈支持,站帮网有你更精彩
www.hzmm999.com
www.wufengbihua.cn
yct598.com
zkqh 发表于 2015-8-3 10:19:14 [Discuz开发] 显示全部楼层

回帖不支持下,期待更多分享。
福州墙绘www.zkqh.net
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

建站高手

精英站长

  • 3489 积分
  • 998 帖数
  • 0 日志
广告招商 QQ: 5620010
快速回复 返回顶部 返回列表