discuz 插件核心函數hookscript分析.

function hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '', $scriptextra = '') {
# 本函數是插件勾注的枋心函數. 對插件開發極爲重要. 咱們一一分析.
# hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '', $scriptextra = '')
# hookscript($script, $hscript, $type = 'funcs', $param = array(), $func = '', $scriptextra = '')
# hookscript(方法名, 類型(好比全局,主題, 移動等等..), 調用類型, 參數, 能夠勾搭一個副方法, 特殊參數);
global $_G; // 引入核心數組, 默認是共計4KB大的數組,
static $pluginclasses; // 靜態貨插件類數組, 以便計算執行文件是否已經被引入過.
if($hscript == 'home') { // 當$hscript 等於home時, 作些變量的轉換, 特殊參數就在這兒有效.
if($script == 'space') {
$scriptextra = !$scriptextra ? $_GET['do'] : $scriptextra;
$script = 'space'.(!empty($scriptextra) ? '_'.$scriptextra : '');
} elseif($script == 'spacecp') {
$scriptextra = !$scriptextra ? $_GET['ac'] : $scriptextra;
$script .= !empty($scriptextra) ? '_'.$scriptextra : '';
}
}

# 判斷插件是否有定義或者開啓. 不然退出.
if(!isset($_G['setting'][HOOKTYPE][$hscript][$script][$type])) {
return;
}
# 判斷插件是否有緩存, 假如沒有則退出.
if(!isset($_G['cache']['plugin'])) {
loadcache('plugin');
}php

# 循環取出module數組, module數組裏麪包涵着文件路徑.
foreach((array)$_G['setting'][HOOKTYPE][$hscript][$script]['module'] as $identifier => $include) {
// pluginrunlist 這兒檢測了方法是否被禁用, 不然跳過一次.
if($_G['pluginrunlist'] && !in_array($identifier, $_G['pluginrunlist'])) {
continue;
}
// 權限的判斷.
$hooksadminid[$identifier] = !$_G['setting'][HOOKTYPE][$hscript][$script]['adminid'][$identifier] || ($_G['setting'][HOOKTYPE][$hscript][$script]['adminid'][$identifier] && $_G['adminid'] > 0 && $_G['setting']['hookscript'][$hscript][$script]['adminid'][$identifier] >= $_G['adminid']);
if($hooksadminid[$identifier]) { // 只有權限判斷經過, 纔會引入文件. 我的以爲應該將$pluginclasses數組運用起來.
@include_once DISCUZ_ROOT.'./source/plugin/'.$include.'.class.php';
}
}

# 判斷方法集是爲數組, (is_array有必要用@抑制錯誤嗎?)
if(@is_array($_G['setting'][HOOKTYPE][$hscript][$script][$type])) {
$_G['inhookscript'] = true; // 只能標明調用成功了.
// 處理附加調用的方法增長, 以便讓循環中可使用.
$funcs = !$func ? $_G['setting'][HOOKTYPE][$hscript][$script][$type] : array($func => $_G['setting'][HOOKTYPE][$hscript][$script][$type][$func]);
// 循環全部的方法. 多維數組, 考慮到一個類型的hook可能有多個實現方法.
foreach($funcs as $hookkey => $hookfuncs) {
foreach($hookfuncs as $hookfunc) {
// $hookfunc[0] 爲 類型也可理解爲類的名字.
// $hookfunc[1] 爲 執行方法
if($hooksadminid[$hookfunc[0]]) {
# 這兒須要重組一下類的名字.
$classkey = (HOOKTYPE != 'hookscriptmobile' ? '' : 'mobile').'plugin_'.($hookfunc[0].($hscript != 'global' ? '_'.$hscript : ''));

# 判斷類沒有被加載就退出. false參數是爲了避免檢查引入.
if(!class_exists($classkey, false)) {
continue;
}
# 判斷若是沒實例化過, 就實例化一次.
if(!isset($pluginclasses[$classkey])) {
$pluginclasses[$classkey] = new $classkey;
}
# 判斷$hookfunc[1]方法不存在實例中. 就退出.
if(!method_exists($pluginclasses[$classkey], $hookfunc[1])) {
continue;
}
# 而後調用$hookfunc[1]方法, 而且植入方法.
$return = $pluginclasses[$classkey]->$hookfunc[1]($param);
// $param = var_export($param,true);
// echo "{$classkey}->$hookfunc[1]($param)<br />"; 可經過這兩行打印具體.

# 判斷 類型具備某特徵, 而且在pluginhooks數組中存在, 而後退出.
if(substr($hookkey, -7) == '_extend' && !empty($_G['setting']['pluginhooks'][$hookkey])) {
continue;
}

# 判斷返回值爲數組時就進入.
if(is_array($return)) {
# $hookkey 判斷 是否存在插件hook當中. 而且要是數組. 接着循環, 將返回值作不一樣的賦值釋放.
if(!isset($_G['setting']['pluginhooks'][$hookkey]) || is_array($_G['setting']['pluginhooks'][$hookkey])) {
foreach($return as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] .= $v;
}
} else {
foreach($return as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] = $v;
}
}
} else {
#假如返回值不是數組, 則換種方法釋放返回值.
if(!is_array($_G['setting']['pluginhooks'][$hookkey])) {
$_G['setting']['pluginhooks'][$hookkey] .= $return;
} else {
foreach($_G['setting']['pluginhooks'][$hookkey] as $k => $v) {
$_G['setting']['pluginhooks'][$hookkey][$k] .= $return;
}
}
}
}
}
}
}
# 變個變量是什麼意思, 上面定義true, 這兒定義false, 是在計算流程是否完成嗎?
$_G['inhookscript'] = false;
}數組

相關文章
相關標籤/搜索