天天看點

Discuz代碼分析——index.php

/*

[Discuz!] (C)2001-2007 Comsenz Inc.

This is NOT a freeware, use is subject to license terms

$Id: index.php 13764 2008-05-19 03:14:01Z heyond $

*/

define('CURSCRIPT', 'index');//定義目前運作腳本名

require_once './include/common.inc.php';//引入common檔案

require_once DISCUZ_ROOT.'./include/forum.func.php';//引入版塊處理函數forum.func.php

$discuz_action = 1;//?

if($cacheindexlife && !$discuz_uid && $showoldetails != 'yes' && (!$_DCACHE['settings']['frameon'] || $_DCACHE['settings']['frameon'] && $_GET['frameon'] != 'yes') && empty($gid)) {

//分析:$cacheindexlife-首頁緩存有效期,$discuz_uid存在,$showoldetails-顯示線上詳情,$_DCACHE['settings']['frameon']-左右分欄模式開關,$gid-版塊組id,自己看看吧,大概就是判斷是否使用一個靜态htm頁面的條件,這個由背景是否開啟首頁緩存時間來決定的

$indexcache = getcacheinfo(0);//得到首頁緩存,此函數見include/forum.func.php 157行,主要是處理index.htm

//下面一段就是判斷是否過期咯,如果過期,就删除index.htm,否則讀取檔案,并根據系統配置決定是否顯示debug資訊

if($timestamp - $indexcache['filemtime'] > $cacheindexlife) {

@unlink($indexcache['filename']);

define('CACHE_FILE', $indexcache['filename']);

$styleid = $_DCACHE['settings']['styleid'];

} elseif($indexcache['filename']) {

@readfile($indexcache['filename']);

$debug && debuginfo();

$debug ? die('<mce:script type="text/javascript"><!--

document.getElementById("debuginfo").innerHTML = " '.($debug ? 'Updated at '.gmdate("H:i:s", $indexcache['filemtime'] + 3600 * 8).', Processed in '.$debuginfo['time'].' second(s), '.$debuginfo['queries'].' Queries'.($gzipcompress ? ', Gzip enabled' : '') : '').'";

// --></mce:script>') : die();

}

}

//$validdays?使用者組有效時間?

$validdays = $discuz_uid && !empty($groupexpiry) && $groupexpiry >= $timestamp ? ceil(($groupexpiry - $timestamp) / 86400) : 0;

//是否顯示線上情況

if(isset($showoldetails)) {

switch($showoldetails) {

case 'no': dsetcookie('onlineindex', 0, 86400 * 365); break;

case 'yes': dsetcookie('onlineindex', 1, 86400 * 365); break;

}

} else {

$showoldetails = false;

}

$currenttime = gmdate($timeformat, $timestamp + $timeoffset * 3600);//目前時間

$lastvisittime = gmdate("$dateformat $timeformat", $lastvisit + $timeoffset * 3600);//上次通路時間

$memberenc = rawurlencode($lastmember);//最後注冊使用者-對URL進行了編碼

$newthreads = round(($timestamp - $lastvisit + 600) / 1000) * 1000;//這個變量不知道幹啥的?

$rsshead = $rssstatus ? ('<link rel="alternate" type="application/rss+xml" title="'.$bbname.'" href="'.$boardurl.'rss.php?auth='.$rssauth." target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="'.$boardurl.'rss.php?auth='.$rssauth." target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" /" />/n") : '';//rss的連結

$customtopics = '';

if($qihoo['maxtopics']) {

foreach(explode("/t", isset($_DCOOKIE['customkw']) ? $_DCOOKIE['customkw'] : '') as $topic) {

$topic = dhtmlspecialchars(trim(stripslashes($topic)));

$customtopics .= '<a href="topic.php?keyword='.rawurlencode($topic).'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="topic.php?keyword='.rawurlencode($topic).'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank">'.$topic.'</a>  ';

}

}//以上兩段,qihoo專題?-背景的擴充-qihoo搜尋那裡可以設定

$hottagstatus = $tagstatus && $hottags && $_DCACHE['tags'];//顯示熱門标簽

$catlist = $forumlist = $sublist = $forumname = $collapseimg = $collapse = array();//初始化區、版塊、子版等數組

$threads = $posts = $todayposts = $fids = $announcepm = 0;//初始化文章、回複、今日回複、版塊id等數組

$postdata = $historyposts ? explode("/t", $historyposts) : array();//曆史發帖?

foreach(array('forumlinks', 'birthdays') as $key) {//處理友情連結與生日使用者的顯示

if(!isset($_COOKIE['discuz_collapse']) || strpos($_COOKIE['discuz_collapse'], $key) === FALSE) {

$collapseimg[$key] = 'collapsed_no.gif';

$collapse[$key] = '';

} else {

$collapseimg[$key] = 'collapsed_yes.gif';

$collapse[$key] = 'display: none';

}

}

$gid = !empty($gid) ? intval($gid) : 0;//區顯示方式

if(!$gid) {//如果不是區顯示方式,即預設的顯示所有版塊的首頁

$announcements = '';//此句與下面一段是處理論壇公告

if($_DCACHE['announcements']) {

$readapmids = !empty($_DCOOKIE['readapmid']) ? explode('D', $_DCOOKIE['readapmid']) : array();

foreach($_DCACHE['announcements'] as $announcement) {

if(empty($announcement['groups']) || in_array($groupid, $announcement['groups'])) {

if(empty($announcement['type'])) {

$announcements .= '<li><a href="announcement.php?id='.$announcement['id'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="announcement.php?id='.$announcement['id'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >'.$announcement['subject'].

'<i>('.gmdate($dateformat, $announcement['starttime'] + $timeoffset * 3600).')</i></a></li>';

} elseif($announcement['type'] == 1) {

$announcements .= '<li><a href="'.$announcement['message'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="'.$announcement['message'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank">'.$announcement['subject'].

'<i>('.gmdate($dateformat, $announcement['starttime'] + $timeoffset * 3600).')</i></a></li>';

}

}

}

}

unset($_DCACHE['announcements']);//得到公告的字元串後,及時清空這個公告數組

//選出論壇清單的sql,注意這裡判斷了是否有通路限制,如果$accessmasks不為空,則根據某使用者的特殊通路規則選出了 a.allowview這個字段等

$sql = !empty($accessmasks) ?

"SELECT f.fid, f.fup, f.type, f.name, f.threads, f.posts, f.todayposts, f.lastpost, f.inheritedmod, f.forumcolumns, f.simple, ff.description, ff.moderators, ff.icon, ff.viewperm, ff.redirect, a.allowview FROM {$tablepre}forums f

LEFT JOIN {$tablepre}forumfields ff ON ff.fid=f.fid

LEFT JOIN {$tablepre}access a ON a.uid='$discuz_uid' AND a.fid=f.fid

WHERE f.status>0 ORDER BY f.type, f.displayorder"

: "SELECT f.fid, f.fup, f.type, f.name, f.threads, f.posts, f.todayposts, f.lastpost, f.inheritedmod, f.forumcolumns, f.simple, ff.description, ff.moderators, ff.icon, ff.viewperm, ff.redirect FROM {$tablepre}forums f

LEFT JOIN {$tablepre}forumfields ff USING(fid)

WHERE f.status>0 ORDER BY f.type, f.displayorder";

$query = $db->query($sql);

while($forum = $db->fetch_array($query)) {//從這裡開始得到兩個重要數組$catlist $forumlist,儲存區資訊與版塊清單資訊

$forumname[$forum['fid']] = strip_tags($forum['name']);//去掉html與php标記,并存入$forumname數組,以fid為鍵

if($forum['type'] != 'group') {//如果是普通版塊(如type=forum或forum=sub)而不是分區

$threads += $forum['threads'];//主題總數

$posts += $forum['posts'];//文章總數(主題與回複)

$todayposts += $forum['todayposts'];//今日文章

if($forum['type'] == 'forum') {//非最終子版(即type不等于sub和group)的版塊

if(forum($forum)) {//forum函數來自include/forum.func.php,處理版塊,得到比如版主啊圖示啊什麼的

$catlist[$forum['fup']]['forums'][] = $forum['fid'];//分區數組$catlist更新

$forum['orderid'] = $catlist[$forum['fup']]['forumscount']++;//得到版塊的排序,所在分區的版塊總數加1,每得到一個子版,就自增1

$forum['subforums'] = '';//将子版字元串設定為空的,這裡不是很明白,forum函數裡得到了一個相同名的字元串,這裡為何要清空?

$forumlist[$forum['fid']] = $forum;//将$forum數組指派給$forumlist的一個元素

}

} elseif(isset($forumlist[$forum['fup']])) {//如果此版塊的父版塊id在$forumlist中存在(由上面的if中得到),則

$forumlist[$forum['fup']]['threads'] += $forum['threads'];

$forumlist[$forum['fup']]['posts'] += $forum['posts'];

$forumlist[$forum['fup']]['todayposts'] += $forum['todayposts'];//累加三個值

if($subforumsindex && $forumlist[$forum['fup']]['permission'] == 2 && !($forumlist[$forum['fup']]['simple'] & 16) || ($forumlist[$forum['fup']]['simple'] & 8)) {

$forumlist[$forum['fup']]['subforums'] .= '<a href="forumdisplay.php?fid='.$forum['fid'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" mce_href="forumdisplay.php?fid='.$forum['fid'].'" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >'.$forum['name'].'</a>  ';

}//對版塊的子版字元串進行處理

}

} else {//否則,如果是分區

if(!isset($_COOKIE['discuz_collapse']) || strpos($_COOKIE['discuz_collapse'], 'category_'.$forum['fid']) === FALSE) {

$forum['collapseimg'] = 'collapsed_no.gif';

$collapse['category_'.$forum['fid']] = '';

} else {

$forum['collapseimg'] = 'collapsed_yes.gif';

$collapse['category_'.$forum['fid']] = 'display: none';

}//上面是對分區開啟關閉按鈕的處理?

if($forum['moderators']) {

$forum['moderators'] = moddisplay($forum['moderators'], 'flat');

}//區版主

$forum['forumscount'] = 0;

$catlist[$forum['fid']] = $forum;//更新區版塊數組

}

}

foreach($catlist as $catid => $category) {//對分區的顯示進行處理,如表格寬度,是否橫排版塊等等

if($catlist[$catid]['forumscount'] && $category['forumcolumns']) {

$catlist[$catid]['forumcolwidth'] = floor(100 / $category['forumcolumns']).'%';

$catlist[$catid]['endrows'] = '';

if($colspan = $category['forumscount'] % $category['forumcolumns']) {

while(($category['forumcolumns'] - $colspan) > 0) {

$catlist[$catid]['endrows'] .= '<td> </td>';

$colspan ++;

}

$catlist[$catid]['endrows'] .= '</tr>';

}

} elseif(empty($category['forumscount'])) {

unset($catlist[$catid]);

}

}

unset($catid, $category);

if(isset($catlist[0]) && $catlist[0]['forumscount']) {//0表示比分區更大一級的一個“虛拟分區”(暫時這麼了解,因為有時候url中有fid=0這樣的出現)

$catlist[0]['fid'] = 0;

$catlist[0]['type'] = 'group';

$catlist[0]['name'] = $bbname;

$catlist[0]['collapseimg'] = 'collapsed_no.gif';

} else {

unset($catlist[0]);

}

if($whosonlinestatus == 1 || $whosonlinestatus == 3) {//顯示線上情況

$whosonlinestatus = 1;

$onlineinfo = explode("/t", $onlinerecord);//$onlineinfo變量,$onlinerecord來自index.php的extract($_DCACHE)處理

if(empty($_DCOOKIE['onlineusernum'])) {

$onlinenum = $db->result_first("SELECT COUNT(*) FROM {$tablepre}sessions");//線上人數

if($onlinenum > $onlineinfo[0]) {//如果目前資料庫中取得的線上人數大于原來線上人數,則更新$onlinerecord

$_DCACHE['settings']['onlinerecord'] = $onlinerecord = "$onlinenum/t$timestamp";

$db->query("UPDATE {$tablepre}settings SET value='$onlinerecord' WHERE variable='onlinerecord'");//同時更新settings表

require_once DISCUZ_ROOT.'./include/cache.func.php';

updatesettings();//更新settings緩存

$onlineinfo = array($onlinenum, $timestamp);//更新$onlineinfo數組

}

dsetcookie('onlineusernum', intval($onlinenum), 300);//将線上人數寫入cookie

} else {

$onlinenum = intval($_DCOOKIE['onlineusernum']);//如果cookie中線上人數不為空,直接讀出

}

$onlineinfo[1] = gmdate($dateformat, $onlineinfo[1] + ($timeoffset * 3600));//更新線上情況的時間戳

$detailstatus = $showoldetails == 'yes' || (((!isset($_DCOOKIE['onlineindex']) && !$whosonline_contract) || $_DCOOKIE['onlineindex']) && $onlinenum < 500 && !$showoldetails);//判斷線上詳情變量,這裡比較複雜,仔細看一下,主要是$showoldetails == 'yes'與cookie中的首頁顯示啊 一些條件

if($detailstatus) {//以下是處理線上人數清單的

@include language('actions');//引用語言檔案 /templates/default/actions.lang.php

$discuz_uid && updatesession();//更新session

$membercount = $invisiblecount = 0;//初始化會員數量及隐身的數量

$whosonline = array();//初始化數組

$maxonlinelist = $maxonlinelist ? $maxonlinelist : 500;//最大線上人數,如果未設定,初始化為500

$query = $db->query("SELECT uid, username, groupid, invisible, action, lastactivity, fid FROM {$tablepre}sessions ".(isset($_DCACHE['onlinelist'][7]) ? '' : 'WHERE uid <> 0')." ORDER BY uid DESC LIMIT ".$maxonlinelist);

while($online = $db->fetch_array($query)) {

if($online['uid']) {//會員

$membercount ++;//會員總數

if($online['invisible']) {//隐身使用者

$invisiblecount++;

continue;

} else {

$online['icon'] = isset($_DCACHE['onlinelist'][$online['groupid']]) ? $_DCACHE['onlinelist'][$online['groupid']] : $_DCACHE['onlinelist'][0];//使用者組的圖示

}

} else {//遊客,差別是資料表session裡,其uid為0

$online['icon'] = $_DCACHE['onlinelist'][7];

$online['username'] = $_DCACHE['onlinelist']['guest'];

}

$online['fid'] = $online['fid'] ? $forumname[$online['fid']] : 0;//使用者正浏覽版塊?

$online['action'] = $actioncode[$online['action']];//使用者正進行的動作

$online['lastactivity'] = gmdate($timeformat, $online['lastactivity'] + ($timeoffset * 3600));//使用者上次通路?

$whosonline[] = $online;//指派給$whosonline數組

}

unset($actioncode, $online);//清空兩個變量

if($onlinenum > $maxonlinelist) {//如果總線上人數大于最大線上人數(系統預設為500),分别取出已登入使用者和隐身使用者

$membercount = $db->result_first("SELECT COUNT(*) FROM {$tablepre}sessions WHERE uid <> '0'");

$invisiblecount = $db->result_first("SELECT COUNT(*) FROM {$tablepre}sessions WHERE invisible = '1'");

}

if($onlinenum < $membercount) {//如果總線上人數小于線上會員數,則更新cookie中的線上使用者人數,注意是onlineusernum而不是onlinenum

$onlinenum = $db->result_first("SELECT COUNT(*) FROM {$tablepre}sessions");

dsetcookie('onlineusernum', intval($onlinenum), 300);

}

//總結:這裡有些混亂,比如總線上人數,線上會員等等,因為變量類似,很容易看錯了解錯誤,多看幾遍吧。。。

$guestcount = $onlinenum - $membercount;

$db->free_result($query);//釋放資料庫連接配接

unset($online);//清空,230行不是有麼?又清空一次?

}

} else {

$whosonlinestatus = 0;//如果背景設定不顯示線上人數,則不顯示線上清單

}

} else {//對應第77行,如果是分區顯示,如url為:index.php?gid=2,則調用下面這個檔案,

require_once DISCUZ_ROOT.'./include/category.inc.php';

}

include template('discuz');//解析首頁的模闆檔案