Discuz!X2 runhooks函数浅析

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()函数,可能还有很多内幕没有挖掘!不过别着急,慢慢来!

您可能还喜欢...