Discuz! X2.5特殊主题:发帖处不显示特殊主题?

这篇日志发布时间已经超过一年,许多内容可能已经失效,请读者酌情参考。

大约半年多没碰康盛的东西了,年前在DZ7.2开发了几个插件,我们这边的开发任务就停止了,现在又有项目需要做dzx2.5的开发,于是开始搞特殊主题。

尼玛我参照开发手册(http://dev.discuz.org/wiki/)写的开始开发,结果就是在论坛的设置处可以看到自定义的特殊主题,发帖的时候却没有这个选项。蛋疼。断断续续折腾了两天,蛋疼,直接翻DZ相关源码,终于找到问题所在:尼玛。。。弄个特殊主题光在论坛设置里面设置还不够,还特么要在用户组给用户使用这个特殊主题的权限。。。

0x01这特么是怎么个情况?

断断续续两天时间,太纠结了。找了个不靠谱的人问了问,毛也没给解决,这些事还是得自力更生。反复测试了很久也没找到问题,索性直接翻DZ相关源码。 入口看URL:

http://dzx/forum.php?mod=post&action=newthread&specialextra=dabing&fid=2&cedit=yes&extra=

,这里以随便找了个安装了特殊主题的插件为例。

首先看forum.php,最后一句required了mod,如下

require DISCUZ_ROOT.'./source/module/forum/forum_'.$mod.'.php';

mod=post,于是找source/module/forum/forum_post.php。 

连个注释也没有,这特么蛋疼,在看action=newthread,直接搜newthread。

在347行找到了newthread的具体处理流程。首先加载缓存处理数据什么的,然后用了libfile函数。

/**
 * 
 * @param string $libname lib的名字,依靠是否有/来判断引用路径
 * @param string $folder 指定引用的二级目录,默认没有
 * @return Ambigous <boolean, string> 如果路径正确则返回包含文件位置,否则返回false
 */
function libfile($libname, $folder = '') {
	$libpath = '/source/'.$folder;
	//处理引用的位置
	if(strstr($libname, '/')) {
		list($pre, $name) = explode('/', $libname);
		$path = "{$libpath}/{$pre}/{$pre}_{$name}";
	} else {
		$path = "{$libpath}/{$libname}";
	}
	//判断是否是合法引用
	return preg_match('/^[\w\d\/_]+$/i', $path) ? realpath(DISCUZ_ROOT.$path.'.php') : false;
}

根据提交的参数libfile('post/newthread', 'include');,打开source/include/post/post_newthread.php。

....
//从第84行开始
	} elseif($specialextra) {
		//开始调用特殊主题
		$threadpluginclass = null;
		if(isset($_G['setting']['threadplugins'][$specialextra]['module'])) {
			//module是特殊主题的类名,就是在模块-特殊主题-名字的地方填写的,这里是preview
			$threadpluginfile = DISCUZ_ROOT.'./source/plugin/'.$_G['setting']['threadplugins'][$specialextra]['module'].'.class.php';
			//可以直接echo出来看看:F:\PHP_Work\DZX\./source/plugin/dabing/preview.class.php
			echo DISCUZ_ROOT.'./source/plugin/'.$_G['setting']['threadplugins'][$specialextra]['module'].'.class.php';
			//开始引用
			if(file_exists($threadpluginfile)) {
				@include_once $threadpluginfile;
				$classname = 'threadplugin_'.$specialextra;//$specialextra这个?应该返回去搜索了。这里是插件的ID
				//在文件存在,类存在,方法存在的情况下,就开始调用该类的newthread方法了。
				if(class_exists($classname) && method_exists($threadpluginclass = new $classname, 'newthread')) {
					$threadplughtml = $threadpluginclass->newthread($_G['fid']);
					$buttontext = lang('plugin/'.$specialextra, $threadpluginclass->buttontext);
					$iconfile = $threadpluginclass->iconfile;
					$iconsflip = array_flip($_G['cache']['icons']);
					$thread['iconid'] = $iconsflip[$iconfile];
				}
			}
		}

顿时觉得特殊主题的逻辑和实现其实超级简单,呵呵。 

然后切换成我们的主题,发现就是不显示,哪怕你手动指定了specialextra也会跳转到发表普通帖子的页面。 

于是回到forum_post.php,肯定对specialextra参数进行了处理。 

在第236行让我吃了一惊,亲,听说过圈复杂度么。。。。莫不是发行版本是经过压缩优化过的?尼玛啊。。。

if($specialextra && $_G['group']['allowpost'] && $_G['setting']['threadplugins'] &&
	(!array_key_exists($specialextra, $_G['setting']['threadplugins']) ||
	!@in_array($specialextra, is_array($_G['forum']['threadplugin']) ? $_G['forum']['threadplugin'] : dunserialize($_G['forum']['threadplugin'])) ||
	!@in_array($specialextra, $_G['group']['allowthreadplugin']))) {
	$specialextra = '';
}

$specialextra:dabing,非空值,true。 

$_G['group']['allowpost']:1,看名字应该是组权限允许发帖),true。 

$_G['setting']['threadplugins']:Array,非空,打印出来是所有的特殊主题的数组,表明存在特殊主题,true。 

 !array_key_exists($specialextra, $_G['setting']['threadplugins']):判断URL输入的特殊主题ID是否真的存在,存在取反,为false。 

三目运算符:is_array($_G['forum']['threadplugin']) ? $_G['forum']['threadplugin'] : dunserialize($_G['forum']['threadplugin'])) :判断该论坛的允许使用的特殊主题列表的保存形式,如果是数组则不变,如果是序列化果断反序列化之,返回数组。这里本来就是数组,无所谓。 

!@in_array($specialextra, $_G['forum']['threadplugin']):这个特殊主题是否在这个论坛中允许使用,这个在论坛的帖子相关设置过,存在取反为false。 

!@in_array($specialextra, $_G['group']['allowthreadplugin']):问题出现了,尼玛这个 $_G['group']['allowthreadplugin']没有刚才自己写的插件的ID,看名字应该是组允许使用的特殊主题列表,这里是false,取反为true。 

 则以上为

if(true && true && true && (false || false || true)) {
	$specialextra = '';
}

最终为true,于是$specialextra被赋空值了。 

根据名字猜测是用户组/管理组权限问题,马上翻后台去看看,果然有这个选项。。。蛋疼。。。看来做DZ二次开发,要同时配备开发手册和使用手册。。。 

到此为止找到原因,突然觉得特殊主题的逻辑好简单:)是否可以山寨一个呢亲? 

呵呵,问题很好解决,关键是又复习了~

0x02DZ特殊主题简单开发教程

首先开启开发者模式,在 config_global.php 后边填一行$_config['plugindeveloper'] = 1;值为1表示开启开发者模式,为2则表示同时开启潜入点提示。写上之后再应用的地方就能看到设计新插件的链接了。 

先照着要求填写相关信息,再切换到模块,添加一个特殊主题。

特殊主题后边有个向下的箭头,点击就可以下载模板,其实可以自己写,写法在手册上。然后返回之前的应用界面,把新插件启用。 

然后在source/plugin下建立dabing目录,然后建立preview.class.php,名字都是上边设置好的,根据自己设置的填写。 然后在preview.class.php写入如下代码:

<?php

class threadplugin_dabing {

	var $name = '测试主题';			//主题类型名称
	var $iconfile = 'icon.gif';		//发布主题链接中的前缀图标
	var $buttontext = '发布测试主题';	//发帖时按钮文字

	function newthread($fid) {
		return "newthread";
	}

	function newthread_submit($fid) {

	}

	function newthread_submit_end($fid, $tid) {

	}

	function editpost($fid, $tid) {
		return "editpost";
	}

	function editpost_submit($fid, $tid) {

	}

	function editpost_submit_end($fid, $tid) {

	}

	function newreply_submit_end($fid, $tid) {

	}

	function viewthread($tid) {
		return "viewthread";
	}
}

注意类名,必须是"threadplugin_"加上你的插件的ID名字,这里是dabing。上边的方法名看名字就能猜个七七八八,具体干啥的看手册(http://dev.discuz.org/wiki/index.php?title=%E7%89%B9%E6%AE%8A%E4%B8%BB%E9%A2%98%E6%A8%A1%E5%9D%97%E5%BC%80%E5%8F%91)。 

然后到工具菜单清理下缓存,再到论坛设置里面,选择帖子设置,就能看到我们的“测试主题”了。


勾选测试主题,OK,这个版块就可以发布测试主题了。赶紧去前台看看。

(图片丢失。。。)

结果在发帖的时候却特么看不到特殊主题,坑爹了,就这个问题,我特么折腾了两天。 

OK,其实还没设置完,来到用户组和管理员组(管理组是基本权限那个设置链接),打开论坛相关的特殊主题,勾选刚才的“测试主题”,赶紧到前台刷新看看,尼玛终于出来了。。。蛋疼

(图片丢失。。。)

当年在学校图书馆看到本DZ7.2论坛使用的书,直接震惊了,现在发现玩好DZ确实需要多熟悉一下这个玩意。。。很奇怪这个问题在网上搜不到,难道只有我遇到了么。。。囧    

留言交流

没有评论
点击换图