使用Ucenter整合wordpress和Discuz (给博客提速)

本博客自从谷歌在内地无法打开之后,打开速度就开始变慢,于是Jhonse哥我作为技术开发猿而言,怎能允许这情况发生?所以就开始给本博客加速了…

第一步: 去掉wordpress默认加载的谷歌字体样式

找到wordpress的核心文件script-loader.php,在/wp-includes目录下

20141208194704

在script-loader.php文件中搜索fonts.googleapis.com,以及ajax.googleapis.com,然后用360提供的前端公共库CDN服务替换即可。请看截图:

20141208195334

20141208195418

20141208195503

第二步: 使用Ucenter整合wordpress和ucenter,来实现更换Gravatar头像

之前使用了第一步的步骤给本博客提速,确确实实速度是提上来了。不过今天本博客又开始慢了,本以为是第一步修改的代码被恢复了,结果一看代码,不是的,原来影响到打开速度慢的是Gravatar头像。

请看分析代码:

在每个文章详细页都有评论页,也就是需要加载评论用户的头像,而首页以及列表页都木有,所以打开首页和列表速度正常,而点击进入详细页就变的特慢。请看加载头像代码。

//评论头像缓存
function deel_avatar($avatar) {
  $tmp = strpos($avatar, 'http');
  $g = substr($avatar, $tmp, strpos($avatar, "'", $tmp) - $tmp);
  $tmp = strpos($g, 'avatar/') + 7;
  $f = substr($g, $tmp, strpos($g, "?", $tmp) - $tmp);
  $w = get_bloginfo('wpurl');
  $e = ABSPATH .'avatar/'. $f .'.png';
  $t = dopt('d_avatarDate')*24*60*60; 
  if ( !is_file($e) || (time() - filemtime($e)) > $t ) 
	copy(htmlspecialchars_decode($g), $e);
  else  
	$avatar = strtr($avatar, array($g => $w.'/avatar/'.$f.'.png'));
  if ( filesize($e) < 500 ) 
	copy(get_bloginfo('template_directory').'/img/default.png', $e);
  return $avatar;
}
//头像缓存  
	if( dopt('d_avatar_b') ){
		add_filter('get_avatar','deel_avatar');  
	}

而deel_avatar函数对应的参数$avatar就是Gravatar头像的html代码,所以只要页面一打开就会加载Gravatar头像的html代码,所以这速度就慢起来了。有的时候直接超时。

于是就想到自己的Jhonse技术论坛对应的有一个Ucenter用户系统,所以就想到用Ucenter来整合wordpress和discuz,来实现用户评论头像为Jhonse技术论坛的用户头像。

说了这么多废话,开始进入主题来整合…

下载wordpress插件: Ucenter

本来自己想开发对应的接口的,结果竟然有前辈已写好,那就直接用咯。(给自己偷懒的借口)

20141208201215

安装之后,开始配置Ucenter插件

20141208201637

在此配置的前提是你需要在Ucenter中添加其应用。

20141208201818

而且需要连接成功!

20141208201908

配置完成之后,还需要修改ucenter提供的代码。请看如下步骤:

找到插件的ucenter.php文件,ucenter插件目录下。

20141208202251

找到get_avatar方法

function get_avatar( $avatar, $id_or_email, $size, $default, $alt ) {
		$user_login = "";
		if ( is_numeric( $id_or_email ) ) {
			$id = (int) $id_or_email;
			$user = get_userdata( $id );
			if ( $user )
				$user_login = $user->user_login;
		} elseif ( is_object( $id_or_email ) ) {
			if ( isset( $id_or_email->comment_type ) && '' != $id_or_email->comment_type && 'comment' != $id_or_email->comment_type )
				return false;

			if ( !empty( $id_or_email->user_id ) ) {
				$id = (int) $id_or_email->user_id;
				$user = get_userdata( $id );
				if ( $user )
					$user_login = $user->user_login;
			}
		}
		list( $uid, $_, $_ ) = uc_get_user( $user_login );
		if ( uc_check_avatar( $uid, 'small' ) > 0 ) {
			$src = UC_API . "/avatar.php?uid=$uid&size=small&random=" . rand();
			$avatar = "<img alt='{$alt}' src='{$src}' class='avatar avatar-{$size} photo avatar-default' height='{$size}' width='{$size}' />";
		}
		return $avatar;
	}

此方法为,当参数id_or_email为用户id或者用户对象时,然后获得其用户名,再然后获得其头像。

当用户不存在的时候没有对其进行处理,所以需要这样来操作:

if ( uc_check_avatar( $uid, 'small' ) > 0 ) {
			$src = UC_API . "/avatar.php?uid=$uid&size=small&random=" . rand();
			$avatar = "<img alt='{$alt}' src='{$src}' class='avatar avatar-{$size} photo avatar-default' height='{$size}' width='{$size}' />";
		}else{
			$src = UC_API . "/avatar.php?uid=0&size=small&random=" . rand();
			$avatar = "<img alt='{$alt}' src='{$src}' class='avatar avatar-{$size} photo avatar-default' height='{$size}' width='{$size}' />";
		}

还有一个没有针对用户的email来操作。因为在评论信息中,传过来的值就是email,所以就需要添加对email的处理。

第一步: 在$user_login初始化的时候直接赋值为$id_or_email

$user_login = $id_or_email;

第二步: 修改ucenter核心文件user.php

通过ucenter获得用户信息。调用流程如下:

uc_get_user ->  client/client.php文件(uc_get_user方法) -> client/control/user.php文件(onget_user方法)

此方法是通过用户名或者用户ID来获得用户信息。

function onget_user() {
		$this->init_input();
		$username = $this->input('username');
		if(!$this->input('isuid')) {
			$status = $_ENV['user']->get_user_by_username($username);
		} else {
			$status = $_ENV['user']->get_user_by_uid($username);
		}
		if($status) {
			return array($status['uid'],$status['username'],$status['email']);
		} else {
			return 0;
		}
	}

所以我们需要添加通过用户邮箱来获得用户信息

function onget_user() {
		$this->init_input();
		$username = $this->input('username');
		if(!$this->input('isuid')) {
			$status = $_ENV['user']->get_user_by_username($username);
			if(!$status){
				$status = $_ENV['user']->get_user_by_email($username);
			}
		} else {
			$status = $_ENV['user']->get_user_by_uid($username);
		}
		if($status) {
			return array($status['uid'],$status['username'],$status['email']);
		} else {
			return 0;
		}
	}

这样就完成了整合工作了.

说了这么多废话,看看效果图:

20141208204100

discuz发帖时标题实现高亮功能

discuz虽然有高亮功能,但不是在发帖的时候,可以选择高亮功能,而是对已经发帖成功的主题进行设置,请看如下截图:

20140804040205

 

而我们要实现的功能是: 在发帖的时候,可以选择高亮功能。

实现步骤:

第一步:修改模板文件

先找到模板文件template/模板风格目录/fourm/post_editor_extra.htm

找到标题(subject)显示位置

<!--{if $_GET[action] != 'reply'}-->
				<span><input type="text" name="subject" id="subject" class="px" value="$postinfo[subject]" {if $_GET[action] == 'newthread'}onblur="if($('tags')){relatekw('-1','-1'{if $_G['group']['allowposttag']},function(){extraCheck(4)}{/if});doane();}"{/if} onkeyup="strLenCalc(this, 'checklen', 80);" style="width: 25em" tabindex="1" /></span>
			<!--{else}-->
				<span id="subjecthide" class="z">RE: $thread[subject] [<a href="javascript:;" onclick="display('subjecthide');display('subjectbox');$('subject').value='RE: {echo dhtmlspecialchars(str_replace('\'', '\\\'', $thread[subject]))}';display('subjectchk');strLenCalc($('subject'), 'checklen', 80);return false;">{lang modify}</a>]</span>
				<span id="subjectbox" style="display:none"><input type="text" name="subject" id="subject" class="px" value="" onkeyup="strLenCalc(this, 'checklen', 80);" style="width: 25em" /></span>
			<!--{/if}-->

这里判断是否为回帖,发帖/编辑贴

然后添加高亮功能代码(可以copy它自带的功能)

<!--{if $_GET[action] != 'reply'}-->
				<span><input type="text" name="subject" id="subject" class="px" value="$postinfo[subject]" {if $_GET[action] == 'newthread'}onblur="if($('tags')){relatekw('-1','-1'{if $_G['group']['allowposttag']},function(){extraCheck(4)}{/if});doane();}"{/if} onkeyup="strLenCalc(this, 'checklen', 80);" style="width: 25em" tabindex="1" /></span>
				<!--{if $_G[jhonse][thread][highlight]}-->
				<span class="dopt">
					<span class="hasd">    
						<input type="hidden" id="highlight_color" name="highlight_color" value="$colorcheck" />
						<input type="hidden" id="highlight_style_1" name="highlight_style[1]" value="$stylecheck[1]" />
						<input type="hidden" id="highlight_style_2" name="highlight_style[2]" value="$stylecheck[2]" />
						<input type="hidden" id="highlight_style_3" name="highlight_style[3]" value="$stylecheck[3]" />
						<a href="javascript:;" id="highlight_color_ctrl" onclick="showHighLightColor('highlight_color')" class="pn colorwd" /></a>
						<a href="javascript:;" id="highlight_op_1" onclick="switchhl(this, 1)" class="dopt_b{if $stylecheck[1]} cnt{/if}" style="text-decoration:none;font-weight:700" title="{lang e_bold}">B</a>
						<a href="javascript:;" id="highlight_op_2" onclick="switchhl(this, 2)" class="dopt_i{if $stylecheck[2]} cnt{/if}" style="text-decoration:none;font-style:italic" title="{lang e_italic}">I</a>
						<a href="javascript:;" id="highlight_op_3" onclick="switchhl(this, 3)" class="dopt_l{if $stylecheck[3]} cnt{/if}" style="text-decoration:underline" title="{lang e_underline}">U</a>
					</span>
				</span>
					<script>
					{if $colorcheck != ''}
					var coloroptions = {'0' : '#000', '1' : '#FF0000', '2' : '#2B65B7', '3' : '#3C9D40'};
					$('highlight_color_ctrl').style.backgroundColor = coloroptions[{$colorcheck}];
					{/if}
					function switchhl(obj, v) {
						if(parseInt($('highlight_style_' + v).value)) {
							$('highlight_style_' + v).value = 0;
							obj.className = obj.className.replace(/ cnt/, '');
						} else {
							$('highlight_style_' + v).value = 1;
							obj.className += ' cnt';
						}
					}
					function showHighLightColor(hlid) {
						var showid = hlid + '_ctrl';
						if(!$(showid + '_menu')) {
							var str = '';
							var coloroptions = {'0' : '#000', '1' : '#FF0000', '2' : '#2B65B7', '3' : '#3C9D40'};
							var menu = document.createElement('div');
							menu.id = showid + '_menu';
							menu.className = 'cmen';
							menu.style.display = 'none';
							for(var i in coloroptions) {
								str += '<a href="javascript:;" onclick="$(\'' + hlid + '\').value=' + i + ';$(\'' + showid + '\').style.backgroundColor=\'' + coloroptions[i] + '\';hideMenu(\'' + menu.id + '\')" style="background:' + coloroptions[i] + ';color:' + coloroptions[i] + ';">' + coloroptions[i] + '</a>';
							}
							menu.innerHTML = str;
							$('append_parent').appendChild(menu);
						}
						showMenu({'ctrlid':hlid + '_ctrl','evt':'click','showid':showid});
					}
					</script>
				<!--{/if}-->
			<!--{else}-->
				<span id="subjecthide" class="z">RE: $thread[subject] [<a href="javascript:;" onclick="display('subjecthide');display('subjectbox');$('subject').value='RE: {echo dhtmlspecialchars(str_replace('\'', '\\\'', $thread[subject]))}';display('subjectchk');strLenCalc($('subject'), 'checklen', 80);return false;">{lang modify}</a>]</span>
				<span id="subjectbox" style="display:none"><input type="text" name="subject" id="subject" class="px" value="" onkeyup="strLenCalc(this, 'checklen', 80);" style="width: 25em" /></span>
			<!--{/if}-->

这里写的是插件来控制用户组使用高亮功能。

效果图如下:

20140804041444

第二步:  处理提交的数据

我们先看提交链接: forum.php?mod=post&action=newthread&fid=184&extra=&topicsubmit=yes

找到模块文件: /source/module/forum/forum_post.php

然后我们看如下代码:

if($_GET['action'] == 'newthread' || $_GET['action'] == 'newtrade') {
	loadcache('groupreadaccess');
	$navtitle .= ' - '.$_G['forum']['name'];
	require_once libfile('post/newthread', 'include');
} elseif($_GET['action'] == 'reply') {
	$navtitle .= ' - '.$thread['subject'].' - '.$_G['forum']['name'];
	require_once libfile('post/newreply', 'include');
} elseif($_GET['action'] == 'edit') {
	loadcache('groupreadaccess');
	$navtitle .= ' - '.$thread['subject'].' - '.$_G['forum']['name'];
	require_once libfile('post/editpost', 'include');
}

然后再找include目录下的文件post/post_newthread.php文件,对提交过来的高亮数据进行处理,请看如下代码:

/*添加highlight字段参数*/
	if(isset($_POST['highlight_color']) && isset($_POST['highlight_style'])){
		$highlight_color = $_POST['highlight_color'];
		$highlight_style = $_POST['highlight_style'];
		$highlight_style_data = $highlight_style[1] . $highlight_style[2] . $highlight_style[3];
		$highlight_style_data = sprintf('%03d', $highlight_style_data);
		$highlight_style_data = bindec($highlight_style_data);
		$highlight = $highlight_style_data.$highlight_color;
		$params['highlight'] = $highlight;
	}else{
		$params['highlight'] = 0;
	}

注:  字体颜色、加粗、斜线、下划线组合成数字存放在highlight字段中。

我们先看插入数据的代码:

$return = $modthread->newthread($params);

采用了$modthread对象的方法

而$nodthread对象是通过代码来实例化的

$modthread = C::m('forum_thread');

说明: C::m 对应的是 model_forum_thread,而C::t 对应的是table_forum_thread

所以我们去找/source/class/model/model_forum_thread.php文件

找到newthread方法

发现此方法调用了

$this->_init_parameters($parameters);

 

protected function _init_parameters($parameters){

		$varname = array(
			'member', 'group', 'forum', 'extramessage',
			'subject', 'sticktopic', 'save', 'ordertype', 'hiddenreplies',
			'allownoticeauthor', 'readperm', 'price', 'typeid', 'sortid',
			'publishdate', 'digest', 'moderated', 'tstatus', 'isgroup', 'imgcontent', 'imgcontentwidth',
			'replycredit', 'closed', 'special', 'tags',
			'message','clientip', 'invisible', 'isanonymous', 'usesig',
			'htmlon', 'bbcodeoff', 'smileyoff', 'parseurloff', 'pstatus', 'geoloc','highlight',
		);
		foreach($varname as $name) {
			if(!isset($this->param[$name]) && isset($parameters[$name])) {
				$this->param[$name] = $parameters[$name];
			}
		}

	}

此方法对传过来的参数以及值进行初始化,所以在$varname数组中添加’highlight’,不然高亮数据就不会入库。

再接着看newthread方法,找到入库代码:

$newthread = array(
			'fid' => $this->forum['fid'],
			'posttableid' => 0,
			'readperm' => $this->param['readperm'],
			'price' => $this->param['price'],
			'typeid' => $this->param['typeid'],
			'sortid' => $this->param['sortid'],
			'author' => $author,
			'authorid' => $this->member['uid'],
			'subject' => $this->param['subject'],
			'dateline' => $this->param['publishdate'],
			'lastpost' => $this->param['publishdate'],
			'lastposter' => $author,
			'displayorder' => $this->param['displayorder'],
			'highlight' => $this->param['highlight'],
			'digest' => $this->param['digest'],
			'special' => $this->param['special'],
			'attachment' => 0,
			'moderated' => $this->param['moderated'],
			'status' => $this->param['tstatus'],
			'isgroup' => $this->param['isgroup'],
			'replycredit' => $this->param['replycredit'],
			'closed' => $this->param['closed'] ? 1 : 0
		);
		$this->tid = C::t('forum_thread')->insert($newthread, true);

再把hightlight添加进去。

然后对应的更新完所有改过的数据,发帖高亮就实现了。

对于编辑帖子高亮,请参照以上步骤修改即可。

第三步: 完毕

Discuz模板中使用cutstr来截取字符串

给Discuz写模板的时候需要对字符串进行截取,可以使用cutstr方法来截取。请看实现代码:

<!--{eval echo cutstr($value['subject'],30,'');}-->

cutstr方法代码如下:

/**
* [discuz] 基于PHP没有安装 mb_substr 等扩展截取字符串,如果截取中文字则按2个字符计算
* @param $string 要截取的字符串
* @param $length 要截取的字符数
* @param $dot 替换截掉部分的结尾字符串
* @return 返回截取后的字符串
*/
function cutstr($string, $length, $dot = '...') {
// 如果字符串小于要截取的长度则直接返回
// 此处使用strlen获取字符串长度有很大的弊病,比如对字符串“新年快乐”要截取4个中文字符,
// 那么必须知道这4个中文字符的字节数,否则返回的字符串可能会是“新年快乐...”
if (strlen($string) <= $length) {
return $string;
}

// 转换原字符串中htmlspecialchars
$pre = chr(1);
$end = chr(1);
$string = str_replace ( array ('&amp;', '&quot;', '&lt;', '&gt;' ), array ($pre . '&' . $end, $pre . '"' . $end, $pre . '<' . $end, $pre . '>' . $end ), $string );

$strcut = ''; // 初始化返回值

// 如果是utf-8编码(这个判断有点不全,有可能是utf8)
if (strtolower ( CHARSET ) == 'utf-8') {
// 初始连续循环指针$n,最后一个字位数$tn,截取的字符数$noc
$n = $tn = $noc = 0;
while ( $n < strlen ( $string ) ) {
$t = ord ( $string [$n] );

if ($t == 9 || $t == 10 || (32 <= $t && $t <= 126)) {
// 如果是英语半角符号等,$n指针后移1位,$tn最后字是1位
$tn = 1;
$n++;
$noc++;
} elseif (194 <= $t && $t <= 223) {
// 如果是二字节字符$n指针后移2位,$tn最后字是2位
$tn = 2;
$n += 2;
$noc += 2;
} elseif (224 <= $t && $t <= 239) {
// 如果是三字节(可以理解为中字词),$n后移3位,$tn最后字是3位
$tn = 3;
$n += 3;
$noc += 2;
} elseif (240 <= $t && $t <= 247) {
$tn = 4;
$n += 4;
$noc += 2;
} elseif (248 <= $t && $t <= 251) {
$tn = 5;
$n += 5;
$noc += 2;
} elseif ($t == 252 || $t == 253) {
$tn = 6;
$n += 6;
$noc += 2;
} else {
$n++;
}

// 超过了要取的数就跳出连续循环
if ($noc >= $length) {
break;
}
}

// 这个地方是把最后一个字去掉,以备加$dot
if ($noc > $length) {
$n -= $tn;
}

$strcut = substr ( $string, 0, $n );

} else {
// 并非utf-8编码的全角就后移2位
for ($i = 0; $i < $length; $i ++) {
$strcut .= ord ( $string [$i] ) > 127 ? $string [$i] . $string [++ $i] : $string [$i];
}
}

// 再还原最初的htmlspecialchars
$strcut = str_replace( array ($pre . '&' . $end, $pre . '"' . $end, $pre . '<' . $end, $pre . '>' . $end ), array ('&amp;', '&quot;', '&lt;', '&gt;' ), $strcut );

$pos = strrpos ( $strcut, chr ( 1 ) );
if ($pos !== false) {
$strcut = substr ( $strcut, 0, $pos );
}

return $strcut . $dot; // 最后把截取加上$dot输出
}

【discuz】解决博文调用新浪图片不显示的问题

最近发布博文的时候,出现一个很纠结的问题:调用新浪博客上的图片的时候,不显示对应的图片,而是显示如下截图:

 

解决方法:

一开始想到用iframe框架直接显示图片,结果一测试还是行不通依然显示以上的状况。最后就想到是用php读取图片文件,然后再显示到iframe框架里。测试就成功了。

代码如下:

js代码:

$("#blog_article img").each(function(index){

		var width = $(this).attr("width");

		var height = $(this).attr("height");

		if(typeof(width) == "undefined"){
			width = 600;
		}

		if(typeof(height) == "undefined"){
			height = 400;
		}

		var src = $(this).attr("src");

		//http://www.huarengolf.com/

		if(src.substring(0,26) != "http://www.huarengolf.com/"){

			var Frame = "<iframe src=\"static/js/jhonse_blog/run.php?Url=" + src + "\" width=\"" + width + "\" height=\"" + height + 
			"\" scrolling=\"no\" frameborder=\"0\" style=\"border:1px solid #ccc;text-align:center;margin: 10px auto;\"></iframe>";

			$(this).parent().html(Frame);

		}

	});

说明: 将原来的图片替换成iframe框架的图片。

php代码:

<?php

	$url = $_GET['Url'];

	$fp = @fopen($url,"r") or die("error");

	$fcontents = @file_get_contents($url);

	header("Content-type: image/JPEG",true);

	echo $fcontents;

?>

 

【discuz】注册页面去掉包含敏感字符功能

今天公司论坛上有人注册账号的时候,出现一个问题?就是在填写用户名的是输入了两个单词,而中间有空格,结果就提示包含敏感字符。看如下截图:

老总要求去掉这个提示,允许有空格,没办法,找到注册页面文件(register.htm),在.\template\default\member\目录下,打开文件一看,原来是通过js代码来控制的,请看如下代码:

<script type="text/javascript" src="{$this->setting[jspath]}register.js?{VERHASH}"></script>

找到对应的js文件:./static/js/register.js

formNode[stmp[0]].onblur = function () {

		checkusername(formNode[stmp[0]].id);

	}

进行修改就可以了。

【discuz】自由修改用户默认头像大小教程

根目录/uc_server/images/noavatar_big.gif (discuz!X2.0自带图片规格 200*200)

根目录/uc_server/images/noavatar_middle.gif (discuz!X2.0自带图片规格 120*120)

根目录/uc_server/images/noavatar_small.gif (discuz!X2.0自带图片规格 50*50)

替换的话,做这大小差不多的直接换就行,不换的话就接着往下看。

在用户上传头像的时候X2就已经自动划分为big/middle/small三种了,不过默认的情况下用户头像只显示middle。
调用的代码如下:

avatar.php?uid=1&size=middle

把middle改成big就好。

查到 template\default\forum\viewhread_node.htm 的相关代码为:

<div onmouseover=”showauthor(this, ‘userinfo$post[pid]’)”><a href=”home.php?mod=space&uid=$post[authorid]” target=”_blank”>$post[avatar]</a></div>

然后查$post[avatar]的赋值在 source\module\forum\forum_viewthread.php 中

$post[‘avatar’] = avatar($post[‘authorid’]);

我们改为

$post[‘avatar’] = avatar($post[‘authorid’],big);

大头像显示搞定~。(想显示小头像就将big替换为small)
当然,此时在样式上是有问题的,所以我们还需要调整一下样式。(调整宽度)
template\default\forum\common\module.css

.pls { width: 160px; 改为 .pls { width: 180px;

.bui { position: absolute; margin: -1px 0 0 -1px; padding: 15px 0 15px 20px; width: 430px !important;改为.bui { position: absolute; margin: -1px 0 0 -1px; padding: 15px 0 15px 20px; width: 450px !important;

到这基本就算是完成了。

二,走到上面那步可以不看下面的,也可以继续看下去。
下面呢就是自行修改头像大小,在上面的基本上再加些。
改将big类型的头像进行缩小:

找到uc_server/control/user.php

{
file_exists($bigavatarfile) && unlink($bigavatarfile);
file_exists($middleavatarfile) && unlink($middleavatarfile);
file_exists($smallavatarfile) && unlink($smallavatarfile);
$success = 0;
}

$filetype = ‘.jpg’;

在下面添加

//{{{对头像大图处理
if($biginfo[0]>133 || $biginfo[1]>180){
if(133/180 > $biginfo[0]/$biginfo[1]){
$_h = 180;
$_w = $biginfo[0] * 180 / $biginfo[1];
}else{
$_w = 133;
$_h = $biginfo[1] * 133 / $biginfo[0];
}
$_im = imagecreatetruecolor($_w, $_h);
$_bg = imagecolorallocate($_im, 255, 255, 255);
imagefill($_im, 0, 0, $_bg);
$_im2 = imagecreatefromjpeg($bigavatarfile);
imagecopyresampled($_im, $_im2 ,0, 0, 0, 0,$_w,$_h,$biginfo[0], $biginfo[1]);
imagedestroy($_im2);
clearstatcache();
imagejpeg($_im,$bigavatarfile,100);
imagedestroy($_im);
}
//对头像大图处理}}}

这样就可以了。