discuzX1.5浅析之广场栏目--runhooks()

来源:互联网 发布:古代汉语文学硕士知乎 编辑:程序博客网 时间:2024/04/30 15:33
 

2010年11月19日 星期五 下午 02:31

runhooks()函数从名字来分析也是加载插件的,也是二次开发中最为重要的环节!也是哥之所以分析代码的初衷!
开始之前,先介绍一下上下文环境,首先从帖子标题可以看出是在广场栏目中,然后是我只开启了“马甲”插件(默认自带的)。杯具的是貌似BBS首页似乎不会激活这个插件!我还没测试BBS的其他子模块!不过大概看了一下这个函数的代码,还是有章法可循的!下面我就个人的理解试着分析一下!

function runhooks() {
global $_G;
if(defined('CURMODULE')) {
hookscript(CURMODULE, $_G['basescript']);
if(($do = !empty($_G['gp_do']) ? $_G['gp_do'] : (!empty($_GET['do']) ? $_GET['do'] : ''))) {
hookscript(CURMODULE, $_G['basescript'].'_'.$do);
}
}
}

就这个函数本身而言,其实没几行代码,不过核心逻辑都在hookscript()里,所以它就显的很单薄!可以看的出来,插件依赖CURMODULE,$_G['basecript'],$_G['gp_do'],$_GET['do']这几个值,把它们拼装起来可以用于在$_G['setting']['hookscript']多维数组中定位要加载的插件信息!

这里要回忆一下$discuz->init()的运行过程,其中的_init_setting()的相关代码如下:

if($this->init_setting) {
if(empty($this->var['setting'])) {
$this->cachelist[] = 'setting';
}

这部分的内容我在先前的相关帖中已经分析过了,不明白的朋友可以哥的空间内搜索帖子!

大家可以利用debug追踪一下数据,我贴出我的这个$_G['setting']['hookscript']数据结构:



老实说,这张图没太大的利用价值,至少就目前的上下文环境,是匹配不到合适的插件的!
不过还是可以让我们了解它的大致结构,有利于下面的代码分析!


下面就开始分析一下hookscript()这个很重要的函数,先看一下它的参数表:

function hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '')

$script指明了此插件在哪个模块执行(其实就是$mod,理解成动作比较顺口);
$hscript指明了此插件属于哪个板块(form,gropu,member,misc,plugin,portal,userapp,search等,每个都对应一个入口文件);
$type指明了此插件的调用类型(这个我也拿不准,错了表怪俺);
$param提供调用此插件方法时需要传递的参数;
$func指明了要调用此插件的哪些可执行方法。

再看它的内部代码,注意static $pluginclasses;作用不用多说了吧?

我暂时还不清楚为什么要有下面这个操作:

if(!isset($_G['cache']['plugin'])) {
loadcache('plugin');
}

加载plugin缓存的作用是什么哪?我估计后面的分析中会揭开这个疑问!
出除此之外,这个函数就没什么难点了吧?
再贴出来一行比较重要的代码:
$return = $pluginclasses[$classkey]->$hookfunc[1]($param);

最后把插件指定方法的返回值存入$_G['setting']['pluginhooks'][$hookkey]中!!

还有一个重点是:插件的标识符($hooksadminid[$identifier])很重要,通过它可以决定是否加载该插件的文件,从而决定是否激活该插件!

细心的朋友应该注意到在上面的图中,有看到一个global配置数组吧?从名字判断,它应该指定的是全局要加载的插件,可是我花了老大劲儿在代码里翻腾,怎么也找不到这全局插件的调用位置!不过,最后总算让俺捕捉到了一些痕迹,在模板文件的头部有一个函数调用代码:hookscriptoutput('discuz')!

function hookscriptoutput($tplfile) {
global $_G;
hookscript('global', 'global');
if(defined('CURMODULE')) {
$param = array('template' => $tplfile, 'message' => $_G['hookscriptmessage'], 'values' => $_G['hookscriptvalues']);
hookscript(CURMODULE, $_G['basescript'], 'outputfuncs', $param);
if(($do = !empty($_G['gp_do']) ? $_G['gp_do'] : (!empty($_GET['do']) ? $_GET['do'] : ''))) {
hookscript(CURMODULE, $_G['basescript'].'_'.$do, 'outputfuncs', $param);
}
}
}

不用解释了吧,这就是执行全局插件的赤裸裸的证据!


好,到此为止就算简单的分析完了runhooks()函数,可能还有很多内幕没有挖掘!不过别着急,慢慢来!

最后重申,哥之所以看DX的代码,就是为了深刻的理解它的插件机制!所以以后肯定还会有插件的帖子,到时候再更深层次的去分析!

到此为止,就结贴了唷~~下次见~

 

原创粉丝点击