分类 代码分析 下的文章

x2的回帖奖励功能分析

进入source\include\post\post_newreply.php文件,在438行附近找到如下代码:

if($thread['replycredit'] > 0 && $thread['authorid'] != $_G['uid'] && $_G['uid']) {

如果$thread['replycredit']大于0,同时帖子作者不是当前登录用户,则进入下面的处理流程。
$thread['replycredit']为当前帖子的回帖奖励总积分。

$replycredit_rule = DB::fetch_first("SELECT * FROM ".DB::table('forum_replycredit')." WHERE tid = '$_G[tid]' LIMIT 1");
$have_replycredit = DB::result_first("SELECT COUNT(*) FROM ".DB::table('common_credit_log')." WHERE relatedid = '{$_G[tid]}' AND uid = '{$_G[uid]}' AND operation = 'RCA' LIMIT {$replycredit_rule['times']} ");

$replycredit_rule为从forum_replycredit表中查询该帖的回帖奖励设置数组,具体格式为

array(
        'tid' => '帖子tid',
        'extcredits' => '每次回帖的奖励积分',
        'times' => '奖励次数',
        'membertimes' => '每个人最多奖励的次数',
        'random' => '中奖率',
        'extcreditstype' => '奖励的积分类型',
)

$have_replycredit为从common_credit_log表中查询该帖中当前登录用户的已奖励次数。

if($replycredit_rule['membertimes'] - $have_replycredit > 0 && $thread['replycredit'] - $replycredit_rule['extcredits'] >= 0) {

如果该帖的每个人最多奖励次数$replycredit_rule['membertimes']大于该帖中当前登录用户的已奖励次数$have_replycredit,同时该帖的回帖奖励总积分$thread['replycredit']大于或等于该帖每次回帖的奖励积分$replycredit_rule['extcredits']。

$replycredit_rule['extcreditstype'] = $replycredit_rule['extcreditstype'] ? $replycredit_rule['extcreditstype'] : $_G['setting']['creditstransextra'][10];

$replycredit_rule['extcreditstype']为该帖奖励积分的积分类型,如果存在$replycredit_rule['extcreditstype']的话就为$replycredit_rule['extcreditstype'],否则为$_G['setting']['creditstransextra'][10]。
$_G['setting']['creditstransextra'][10]为后台->全局->积分设置下设置的回帖奖励使用的积分。

if($replycredit_rule['random'] > 0) {
                $rand = rand(1, 100);
                $rand_replycredit = $rand <= $replycredit_rule['random'] ? true : false ;
} else {
                $rand_replycredit = true;
}

如果该帖回帖奖励的中奖率$replycredit_rule['random']大于0:
$rand为在1-100中间生成的一个随机数,如果$rand小于或等于$replycredit_rule['random'],则设置$rand_replycredit为true,否则为false。
如果该帖回帖奖励的中奖率$replycredit_rule['random']不大于0:
设置$rand_replycredit为true。

if($rand_replycredit) {
                if(!$posttable) {
                                $posttable = getposttablebytid($_G['tid']);
                }
                updatemembercount($_G['uid'], array($replycredit_rule['extcreditstype'] => $replycredit_rule['extcredits']), 1, 'RCA', $_G[tid]);
                DB::update($posttable, array('replycredit' => $replycredit_rule['extcredits']), array('pid' => $pid));
                DB::update("forum_thread", array('replycredit' => $thread['replycredit'] - $replycredit_rule['extcredits']), array('tid' => $_G[tid]));
}

如果存在$rand_replycredit:

if(!$posttable) {
$posttable = getposttablebytid($_G['tid']);
}

如果不存在回帖表$posttable,则通过tid获取$posttable。

updatemembercount($_G['uid'], array($replycredit_rule['extcreditstype'] => $replycredit_rule['extcredits']), 1, 'RCA', $_G[tid]);

根据回帖奖励的规则,更新当前登录用户的积分:在原有积分基础上+$replycredit_rule['extcredits']。$replycredit_rule['extcreditstype']为积分类型,$replycredit_rule['extcredits']为奖励积分数。

DB::update($posttable, array('replycredit' => $replycredit_rule['extcredits']), array('pid' => $pid));

更新回帖表$posttable中当前用户回复的积分奖励。

DB::update("forum_thread", array('replycredit' => $thread['replycredit'] - $replycredit_rule['extcredits']), array('tid' => $_G[tid]));

$thread['replycredit'] - $replycredit_rule['extcredits']为计算回帖奖励的剩余总积分。
更新主题表forum_thread中当前帖子的回帖奖励总积分replycredit。

x2的入口文件index.php文件分析

index.php入口文件是一个跳板文件,最终会跳转到相应的文件或URL。

if(!empty($_SERVER['QUERY_STRING']) && is_numeric($_SERVER['QUERY_STRING'])) {
//$_SERVER['QUERY_STRING']不为空,且为数字
//处理如http://www.a.com/?1的个人空间域名
	$_ENV['curapp'] = 'home';
	$_GET = array('mod'=>'space', 'uid'=>$_SERVER['QUERY_STRING']);
} else {

	$url = '';
	$domain = $_ENV = array();
	$jump = false;
	@include_once './data/cache/cache_domain.php';
	$_ENV['domain'] = $domain;
	//$domain为cache_domain.php缓存文件里的域名数组
	if(empty($_ENV['domain'])) {
	//如果$_ENV['domain']为空
		$_ENV['curapp'] = 'forum';
	} else {
		$_ENV['defaultapp'] = array('portal.php' => 'portal', 'forum.php' => 'forum', 'group.php' => 'group', 'home.php' => 'home');
		$_ENV['hostarr'] = explode('.', $_SERVER['HTTP_HOST']);
		//$_ENV['hostarr']为域名根据.分割后的数组
		$_ENV['domainroot'] = substr($_SERVER['HTTP_HOST'], strpos($_SERVER['HTTP_HOST'], '.')+1);
		//$_ENV['domainroot']为当前地址的根域名
		if(!empty($_ENV['domain']['app']) && is_array($_ENV['domain']['app']) && in_array($_SERVER['HTTP_HOST'], $_ENV['domain']['app'])) {
		//如果$_ENV['domain']['app']不为空,且为数组,同时当前地址的域名在$_ENV['domain']['app']数组中
		//$_ENV['domain']['app']为后台设置的应用域名
			$_ENV['curapp'] = array_search($_SERVER['HTTP_HOST'], $_ENV['domain']['app']);
			//array_search返回在$_ENV['domain']['app']数组中根据键值等于$_SERVER['HTTP_HOST']对应的键值,如不存在则返回false
			if($_ENV['curapp'] == 'mobile') {
			//手机版处理
				$_ENV['curapp'] = 'forum';
				if(@$_GET['mobile'] != 'no') {
					@$_GET['mobile'] = 'yes';
				}
			}
			if($_ENV['curapp'] == 'default' || !isset($_ENV['defaultapp'][$_ENV['curapp'].'.php'])) {
				$_ENV['curapp'] = '';
			}
		} elseif(!empty($_ENV['domain']['root']) && is_array($_ENV['domain']['root']) && in_array($_ENV['domainroot'], $_ENV['domain']['root'])) {
		//如果$_ENV['domain']['root']不为空,且为数组,同时当前地址的根域名$_ENV['domainroot']在$_ENV['domain']['root']数组中
		//$_ENV['domain']['root']为后台设置的根域名
			$_G['setting']['holddomain'] = $_ENV['domain']['holddomain'] ? $_ENV['domain']['holddomain'] : array('www');
			//holddomain为后台设置的保留二级域名
			$list = $_ENV['domain']['list'];
			//$list为论坛分区、板块、专题、频道绑定的域名的集合数组
			if(isset($list[$_SERVER['HTTP_HOST']])) {
			//如果当前域名在数组$list中有设置
				$domain = $list[$_SERVER['HTTP_HOST']];
				//$list[$_SERVER['HTTP_HOST']]为当前域名对应的设置
				$id = intval($domain['id']);
				switch($domain['idtype']) {
					case 'subarea':
					//论坛分区
						$_ENV['curapp'] = 'forum';
						$_GET['gid'] = $id;
						break;
					case 'forum':
					//论坛板块
						$_ENV['curapp'] = 'forum';
						$_GET['mod'] = 'forumdisplay';
						$_GET['fid'] = $id;
						break;
					case 'topic':
					//专题
						$_ENV['curapp'] = 'portal';
						$_GET['mod'] = 'topic';
						$_GET['topicid'] = $id;
						break;
					case 'channel':
					//频道
						$_ENV['curapp'] = 'portal';
						$_GET['mod'] = 'list';
						$_GET['catid'] = $id;
						break;
				}
			} elseif(count($_ENV['hostarr']) > 2 && $_ENV['hostarr'][0] != 'www' && !checkholddomain($_ENV['hostarr'][0])) {
			//如果$_ENV['hostarr']数组的元素个数大于2,且$_ENV['hostarr']的第一个元素不是www(即当前地址的域名前缀不是www),同时$_ENV['hostarr']的第一个元素不是保留二级域名中
			//checkholddomain函数为判断是否为保留二级域名
				$_ENV['prefixdomain'] = addslashes($_ENV['hostarr'][0]);//域名前缀
				$_ENV['domainroot'] = addslashes($_ENV['domainroot']);//当前地址的根域名
				require_once './source/class/class_core.php';
				$discuz = & discuz_core::instance();
				$discuz->init_setting = true;
				$discuz->init_user = false;
				$discuz->init_session = false;
				$discuz->init_cron = false;
				$discuz->init_misc = false;
				$discuz->init_memory = false;
				$discuz->init();
				$jump = true;
				$domain = DB::fetch_first("SELECT * FROM ".DB::table('common_domain')." WHERE domain='$_ENV[prefixdomain]' AND domainroot='$_ENV[domainroot]' LIMIT 1");
				//根据域名前缀和根域名在common_domain表中查询记录
				$apphost = $_ENV['domain']['app'][$domain['idtype']] ? $_ENV['domain']['app'][$domain['idtype']] : $_ENV['domain']['app']['default'];
				//如果存在当前类型的应用域名,则$apphost为当前类型的应用域名,否则为默认域名
				$apphost = $apphost ? 'http://'.$apphost.'/' : '';
				switch($domain['idtype']) {
					case 'home':
					//个人空间的二级域名
						if($_G['setting']['rewritestatus'] && in_array('home_space', $_G['setting']['rewritestatus'])) {
							$url = rewriteoutput('home_space', 1, $apphost, $domain['id']);
						} else {
							$url = $apphost.'home.php?mod=space&uid='.$domain['id'];
						}
						//$url为这个用户的空间地址
						break;
					case 'group':
					//群组的二级域名
						if($_G['setting']['rewritestatus'] && in_array('group_group', $_G['setting']['rewritestatus'])) {
							$url = rewriteoutput('group_group', 1, $apphost, $domain['id']);
						} else {
							$url = $apphost.'forum.php?mod=group&fid='.$domain['id'].'&page=1';
						}
						//$url为这个群组的地址
						break;
				}
			}
		} else {
			$jump = true;
		}
		if(empty($url) && empty($_ENV['curapp'])) {
			if(!empty($_ENV['domain']['defaultindex']) && !$jump) {
			//如果$_ENV['domain']['defaultindex']不为空,且不存在$jump
			//$_ENV['domain']['defaultindex']为后台导航里设置的默认首页
				if($_ENV['defaultapp'][$_ENV['domain']['defaultindex']]) {
					$_ENV['curapp'] = $_ENV['defaultapp'][$_ENV['domain']['defaultindex']];
				} else {
					$url = $_ENV['domain']['defaultindex'];
				}
			} else {
				if($jump) {
					$url = empty($_ENV['domain']['app']['default']) ? (!empty($_ENV['domain']['defaultindex']) ? $_ENV['domain']['defaultindex'] : 'forum.php') : 'http://'.$_ENV['domain']['app']['default'];
					//如果$_ENV['domain']['app']['default']为空,如果$_ENV['domain']['defaultindex']不为空,则$url=$_ENV['domain']['defaultindex'],否则等于forum.php
					//如果$_ENV['domain']['app']['default']不为空,$url='http://'.$_ENV['domain']['app']['default']
					//$_ENV['domain']['app']['default']为后台应用域名下的默认域名
					//$_ENV['domain']['defaultindex']为后台导航下设置的默认首页
				} else {
					$_ENV['curapp'] = 'forum';
				}
			}
		}
	}
}
if(!empty($url)) {
	$delimiter = strrpos($url, '?') ? '&' : '?';
	//如果$url里已经存在?,则连接符$delimiter='&',否则$delimiter='?'
	if($_GET['fromuid']) {
		$url .= $delimiter.'fromuid='.$_GET['fromuid'];
	} elseif($_GET['fromuser']) {
		$url .= $delimiter.'fromuser='.$_GET['fromuser'];
	}
	header("HTTP/1.1 301 Moved Permanently");
	header("location: $url");
	//301跳转到$url地址
} else {
	require './'.$_ENV['curapp'].'.php';
	//加载$_ENV['curapp'].php文件
}

开启防刷新后,个人空间的访问数和日志的浏览数不更新的问题分析

今日无事看了下个人空间的访问数更新处理代码,结果发现开启防刷新后个人空间的访问数无法更新,看过代码后发现根本没有开启防刷新后的代码处理,即开启防刷新后个人空间的访问数不会更新。

下面以个人空间的访问数更新为例,具体分析:
source\include\space\space_index.php文件里,67行附近代码:

if(!$_G['setting']['preventrefresh'] || ($_G['uid'] && !$space['self'] && !in_array($space['uid'], $viewuids))) {
	member_count_update($space['uid'], array('views' => 1));
	$viewuids[$space['uid']] = $space['uid'];
	dsetcookie('viewuids', implode('_', $viewuids));
}

1017日更新:
$_G['setting']['preventrefresh']为后台的查看数开启防刷新的设置,位置在全局->空间设置->基本设置下。
!$_G['setting']['preventrefresh']为未开启此设置。
($_G['uid'] && !$space['self'] && !in_array($space['uid'], $viewuids))为开启后的条件判断,当前登录用户的UID不在$viewuids数组中且不是访问的自己的空间。
$_G['uid']为登录用户的UID。
$space['self']为自己的空间。
$viewuids为从cookie里获取访问过此空间的用户的UID数组。

member_count_update($space['uid'], array('views' => 1));

此段代码即为更新表pre_common_member_home_field里views字段(访问量)。

访问门户频道绑定的域名仍跳转到默认域名下的分析

问题描述:

已在后台->门户->频道栏目下设置某个一级栏目的绑定域名,但是访问此域名,仍会跳转到门户域名下的频道地址上。

如后台设置的新闻频道的绑定域名为news.a.com,设置的默认域名为www.a.com,访问news.a.com会302跳转到www.a.com/portal.php?mod=list&catid=x的地址(www.a.com为门户域名,x为新闻频道的ID)。

 

原因:

绑定的域名生效同时还需要设置频道的目录名称,否则会跳转到门户域名下的频道地址。

 

代码分析:

在cache_portalcategory.php文件中的build_cache_portalcategory函数中,

$domain = $_G['setting']['domain'];
//$_G['setting']['domain']为后台->全局->域名设置下设置的域名,为数组。
$channelrootdomain = !empty($domain['root']) && !empty($domain['root']['channel']) ? $domain['root']['channel'] : '';
//$channelrootdomain为频道根域名,如果没有设置频道根域名则为空。
$portaldomain = '';
if(!empty($domain['app']['portal'])) {
	$portaldomain = 'http://'.$domain['app']['portal'].$_G['siteroot'];
} elseif(!empty($domain['app']['default'])) {
	$portaldomain = 'http://'.$domain['app']['default'].$_G['siteroot'];
} else {
	$portaldomain = $_G['siteurl'];
}
//$portaldomain为门户域名
//$domain['app']['default']为应用域名下的门户域名
//$domain['app']['default']为应用域名下的默认域名
//$_G['siteurl']为站点url

对应关系如下:

if($channelrootdomain && $data[$topid]['domain']){
//如果存在频道根域名,同时设置该频道栏目绑定了域名
	$url = 'http://'.$data[$topid]['domain'].'.'.$channelrootdomain.'/';
	//设置该频道栏目的url为http://频道栏目绑定的域名.频道根域名/
	if($foldername) {
	//如果设置了频道的目录名称
		if(!empty($value['upid'])) {
		//如果存在父级分类
			$url .= $foldername;
			//设置该频道栏目的url为http://频道栏目绑定的域名.频道根域名/频道的目录名称
		}
	} else {
		$url = $portaldomain.'portal.php?mod=list&catid='.$key;
		//没有设置频道的目录名称的话,设置该频道栏目的url为门户域名.poral.php?mod=list&catid=x(x为该频道栏目ID)
		//从这里可以看出来,如果仅设置了频道域名而没有设置频道的目录名称,则频道栏目的url还是会使用门户域名而非频道栏目绑定的域名
	}
} elseif ($foldername) {
//没有设置频道根域名,但是设置了频道的目录名称
	$url = $portaldomain.$foldername;
	//设置该频道栏目的url为门户域名.频道的目录名称
	if(substr($url, -1, 1) != '/') $url.= '/';
} else {
//没有设置频道根域名,没有设置频道的目录名称
	$url = $portaldomain.'portal.php?mod=list&catid='.$key;
	//设置该频道栏目的url为门户域名.portal.php?mod=list&catid=x(x为该频道栏目ID)
}