discuz x1.5 DIY首页, 在首页使用DIY功能,调用其他网站的模块的数据。
上文分析到:
在源文件中搜索“contentblockclass_nav ” 找到了 文件 template\default\portal\portalcp_diy.htm
<div class="tbmu mbm" id="contentblockclass_nav" style="margin-top: -15px">
<!--{loop $_G['cache']['blockclass'] $key $value}-->
<a href="javascript:;" id="bcnav_$key" class="a" onclick="spaceDiy.switchBlockclass('$key');return false;">$value[name]</a>
$key = html group space member forum
$value[name] = 展示类 | 群组类 | 门户类 | 咨询站文章类 | 空间类 | 会员类 | 论坛类
通过以上代码,我们得知 要找到 $_G['cache']['blockclass'] 的定义/赋值;
function block_getclass($classname, $getstyle=false) { // 例如 $calssname = forum_thread
global $_G;
if(!isset($_G['cache']['blockclass'])) {
loadcache('blockclass');
}
$theclass = array();
list($c1, $c2) = explode('_', $classname);// $c1=forum $c2=thread $calssname=forum_thread
if(is_array($_G['cache']['blockclass']) && isset($_G['cache']['blockclass'][$c1]['subs'][$classname])) {
$theclass = $_G['cache']['blockclass'][$c1]['subs'][$classname]; // 一个数组 // $_G['cache']['blockclass'][forum]['subs'][forum_thread
if($getstyle && !isset($theclass['style'])) // $getstyle=true 才有可能 对cache赋值
{
$query = DB::query('SELECT * FROM '.DB::table('common_block_style')." WHERE blockclass='$classname'"); // 'common_block_style'表结构分析
while(($value=DB::fetch($query)))
{
$value['template'] = !empty($value['template']) ? (array)(unserialize($value['template'])) : array();
$value['fields'] = !empty($value['fields']) ? (array)(unserialize($value['fields'])) : array();
$key = 'blockstyle_'.$value['styleid'];
$_G[$key] = $value;
$theclass['style'][$value['styleid']] = $value;
}
$_G['cache']['blockclass'][$c1]['subs'][$classname] = $theclass; // 赋值的地方
// $c1 -- 对应的$key
// 'subs' == -- 对应的$value
// $_G['cache']['blockclass'][$c1]['subs'][name] = 展示类 群组类
}
}
return $theclass;
}
再查找那些地方调用了这个函数呢?
还有 就是 在那些文件中包括了 “展示类 | 群组类 | 门户类 | 咨询站文章类 | 空间类 | 会员类 | 论坛类 ” 的这些文字呢?
在全部源代码中搜索“展示类”,中文定义在 source\language\lang_blockclass.php中
'blockclass_group' => '群组类',
那么查找下 'blockclass_group' 在那里使用/调用了?
在全部源代码中搜索“展示类”,在 source\class\block\group\blockclass.php中使用。
$blockclass = array(
'name' => lang('blockclass', 'blockclass_group'),
);
搜索 其他词,“展示类 | 群组类 | 门户类 | 咨询站文章类 | 空间类 | 会员类 | 论坛类 ” ,都在 blockclass.php中,
只是 这些 blockclass.php在不同的文件夹下,但是在 同一个source\class\block\目录下
目录中有 article 、forum 、group 、html 、member 、portal 、space 分别对应了,“展示类 | 群组类 | 门户类 | 空间类 | 会员类 | 论坛类 ”;
文件中都包含了类似的多个文件:block_****.php
都包含了这个文件 blockclass.php(必须有的文件):
blockclass.php文件内容:
<?php
$blockclass = array(
'name' => lang('blockclass', 'blockclass_****'),
);
?>
要想再扩展一个类似的 ×××类, 我们应该在source\class\block\目录下 新建一个文件夹,文件里里的必须有一个文件叫 blockclass.php,
然后有一些其他文件,block_****.php(必须有的文件)
我们去全部代码中搜索“class/block” 注意,在liunx下 路径要做个 转义符 就是 “class\block” 变为 “class/block” 了。
function blockclass_cache() {
global $_G;
$data = $dirs = $styles = $dataconvert = array();
$dir = DISCUZ_ROOT.'/source/class/block/';
$dh = opendir($dir); // 循环遍历文件夹下的文件
while(($filename=readdir($dh))) {
if(is_dir($dir.$filename) && substr($filename,0,1) != '.') {
$dirs[$filename] = $dir.$filename.'/';
}
}
foreach($dirs as $name=>$dir) {
$blockclass = $blockconvert = array();
if(file_exists($dir.'blockclass.php')) {
include_once($dir.'blockclass.php'); /// 加载了 文件夹下的 blockclass.php文件
}
$dh = opendir($dir); // 再次打开文件夹
while(($filename=readdir($dh))) { // 循环遍历文件
$match = $info = $fieldsconvert = array();
$scriptname = $scriptclass = '';
if(preg_match('/^(block_[\w]+)\.php$/i', $filename, $match)) { // 正则表达式 匹配文件 block_*****.php
$scriptclass = $match[1];
$scriptname = preg_replace('/^block_/i', '', $scriptclass);
include_once $dir.$filename; // 循环 把其他文件也都加载了进来 例如 source\class\block\group\block_group.php block_groupnew.php
if(class_exists($scriptclass)) {
$obj = new $scriptclass(); /// 实例化了 类的对象
if(method_exists($obj, 'name') && method_exists($obj, 'blockclass') && method_exists($obj, 'fields')
&& method_exists($obj, 'getsetting') && method_exists($obj, 'getdata')) {
// 实例化的对象,必须包括这些函数/方法 例如 : 'name','blockclass','fields','getsetting','getdata' 我们新做的扩展类中,必须包括这些函数/方法
$info['name'] = $obj->name();
$info['blockclass'] = $obj->blockclass();
$info['fields'] = $obj->fields();
}
我们也要在全部代码中 ,搜索下 那些程序中调用了这个函数blockclass_cache()呢?
搜索的结果:有两处调用。
1. soucre\admincp\admincp_tools.php 是在管理员 使用 “更新缓存”的菜单时调用的,不太符合我们的逻辑。
2. soucre\module\misc\misc_initsys.php 从文件名称中 大概判断为 initsys 系统初始化时 调用执行了此函数。
soucre\module\misc\misc_initsys.php的文件内容:
require_once libfile('function/cache');
updatecache();
require_once libfile('function/block');
blockclass_cache();
if($_G['config']['output']['tplrefresh']) {
$tpl = dir(DISCUZ_ROOT.'./data/template');
while($entry = $tpl->read()) {
if(preg_match("/\.tpl\.php$/", $entry)) {
@unlink(DISCUZ_ROOT.'./data/template/'.$entry);
}
}
$tpl->close();
}
下边 ,我们分析下 实例化后的 block_member :
class block_member { // 必须有个类的定义
function name() { // //数据来源 下拉框 内容显示 例如:blockclass_member_script_member --- 高级自定义, 我们要扩展的就可以直接为 “启德咨询站 ”
return lang('blockclass', 'blockclass_member_script_member');
}
function blockclass() { // // DIY时的 “模块”的一级菜单, “模块”的 二级菜单显示文字
return array('member', lang('blockclass', 'blockclass_member_member')); // 'blockclass_member_member' => '会员模块',
}
/**
* 返回数据类中可供“模块模板”使用的字段。
* 格式见示例:
* name 为该字段的显示名称
* formtype 决定编辑单条数据时该字段的显示方式: 类型有: text, textarea, date, title, summary, pic; 详见 portalcp_block.htm 模板(搜 $field[formtype] )
* datatype 决定该字段的数据展示,类型有: string, int, date, title, summary, pic; 详见 function_block.php 中 block_template 函数
* @return <type>
*/
function fields() { // 取得数据后,对应的字段分析
global $_G;
}
/**
* 返回使用本数据类调用数据时的设置项
* 格式见示例:
* title 为显示的名称
* type 为表单类型, 有: text, password, number, textarea, radio, select, mselect, mradio, mcheckbox, calendar; 详见 function_block.php 中 block_makeform() 函数
* @return <type>
*/
function getsetting() { // 取得在获取数据时的一些条件设置 例如显示多少条数据? 显示时间啊?
}
/**
* 处理设置参数,返回数据
* 返回数据有两种:
* 一种是返回 html,放到模块 summary 字段,直接显示; 返回格式为: array('html'=>'返回内容', 'data'=>null)
* 一种是返回 data,通过模块样式渲染后展示,返回的数据应该包含 fields() 函数中指定的所有字段; 返回格式为: array('html'=>'', 'data'=>array(array('title'=>'value1'), array('title'=>'value2')))
* 特别的:
* parameter 参数包含 getsetting() 提交后的内容; 并附加了字段:
* items ,为用户指定显示的模块数据条数;
* bannedids ,为用户选择屏蔽某数据时记录在模块中的该数据 id。 应该在获取数据时屏蔽该数据;
*
* 如果返回的数据给 data, 那么应该包含 fields() 函数指定的所有字段。并附加以下字段:
* id 标志该数据的 id,如果用户屏蔽某数据时,会将该数据的 id 添加到 parameter[bannedids] 里
* idtype 标志该数据的 idtype
*
* @param <type> $style 模块样式(见 common_block_style 表)。 可以根据模块样式中用到的字段来选择性的获取/不获取某些数据
* @param <type> $parameter 用户对 getsetting() 给出的表单提交后的内容。
* @return <type>
*/
function getdata($style, $parameter) { // 取得数据的接口
return array('html' => '', 'data' => null);
}
}
===================================================================
要在discuz x1.5中,DIY功能中扩展功能模块/数据模块,我们必须要做的事情/步骤:
1. 在 source\class\block\建立一个文件 例如: eiccms 文件(我们用来调用[size=+0]http://www.eic.org.cn的网站的资讯类数据;文章标题和链接等信息)
2. 在 eiccms文件里 必须包括文件1:blockclass.php
必须包括一个文件:block_eiccms.php 定义一个类 为 class block_eiccms {}
3. 在block_eiccms类中,实现 以下方法:'name','blockclass','fields','getsetting','getdata'
包括了 设置显示的汉字, 包括模板模块中的数据字段,包括取的数据时的条件设置; 包括取出数据的方法(可以直接连接数据库取得数据,也可以使用调用数据接口-http/xml来获取数据)
4. 就可以调试功能了, 这时,每次的调试 都需要“更新缓存” ,然我们不断的调试就可以实现了。
====================================================================
发现 在调用这些函数的地方都有查询数据库的操作: common_block 这个数据表就很关键了
$query = DB::query("SELECT b.*, tb.targettplname FROM ".DB::table('common_block')." b LEFT JOIN ".DB::table('common_template_block')." tb ON b.bid=tb.bid WHERE $wheresql $ordersql LIMIT $start,$perpage");
common_block 这个数据表 字段分析: --- 对应这个表的操作 对应管理后台 :管理后台 --- 门户 --- 模块管理 (在DIY设置模块的参数,例如显示几条/显示什么格式样式/标题等信息) :
blockclass --- 是数据块/模块的名称
例如:
portal_article portal_topic
forum_thread forum_attachment
space_blog
group_thread group_group
name 模块的名称/标识
title 模块的标题
uid username 编辑人的一些信息
picwidth picheight target 图片的一些设置信息
dateformat dateuformat 时间日期格式
param 一些参数设置 序列化数据存储
shownum 显示几条信息
cachetime 缓存时间
common_block_style 这个数据表 字段分析: --- 对这个数据库表的操作在管理后台体现在: 后台管理 ---- 门户 ---- 模块模板(这个管理功能中):
blockclass : html_html forum_forum forum_attachment
name : [X1.5]版块名称列表 [X1.5]版块名称+总帖数 [X1.5]版块名称+总帖数(有序) [X1.5]版块名称+今日发贴数 [X1.5]版块名称+今日发贴数(有序)
template : [size=+0]模块的HTML代码
在 使用discuz管理后台 -- 门户 --- 模块模板/模块管理 这个功能时,
有“模块模板 - 添加”模块模板时,首先要需要“选择模块分类”
有“模块管理 - 数据调用”时, 首先也要选择“模块分类”
----- 我们要分析 这个模块分类和我们使用DIY时的模块分类是不是一样的呢?
分析 “模块模板 - 添加” 的 “选择模块分类”
管理URL是 : http://bbs.dragonchen82.com/admin.php?action=blockstyle
根据 discuz的名称规则, 应该在 soucre\admincp\admincp_blockstyle.php
( discuz x1.5的文件对应规则 ,可查看 文章:“discuz x1.5的 管理后台逻辑分析 admin.php 逻辑分析 ”http://ggmmchou.blog.163.com/blog/static/593331492011444387769/ )
下边分析:admincp_blockstyle.php
if($operation=='add' || $operation=='edit') { // 添加/编辑}
elseif($operation=='delete') { //删除 }
else{ //显示页面
$blockclass_sel = '<select name="blockclass">'; // 通过HTML页面的代码中的 select的名字,在这个文件中找到了位置
$blockclass_sel .= '<option value="">'.cplang('blockstyle_blockclass_sel').'</option>';
foreach($_G['cache']['blockclass'] as $key=>$value) {
}
仍然是 对 $_G['cache']['blockclass'] 的一个循环显示处理。 还得分析 $_G['cache']['blockclass'] 里的内容/值是什么? 在那里赋值的?
又回到了 我们 跟踪的 function_block.php 文件中 对$_G['cache']['blockclass'] 的赋值 :
function block_getclass($classname, $getstyle=false) { } --- 回到了原来的思路上,看来我们得从上一点上 重新分析下思路。
discuz的后台 --- 模块管理 --列表中 的 编辑“属性”
http://bbs.eic.org.cn/portal.php?mod=portalcp&ac=block&op=block&bid=270&from=cp
这个地址 就是 对模块的设置的页面。 --- -- 这个也没有大的帮助,仍然无法找到 如何扩展DIY的数据来源/数据模块。
但是,我们找到了 portalcp_block.php 文件, 分析下这个文件:
include_once libfile('function/block'); // 加载了 function_block.php文件
其他文章:discuz X教程:教你如何添加自定义DIY模块,为模块添加扩展http://www.lifedo.cn/html/79/n-10479.html
打开 source\\class\\block 目录:这个目录是为diy模块产生数据来源的目录,文件名格式为block_xxxx.php,这里文章来源是block_article.php这个文件(基类),其它名字前面类似的是扩展类 ,比如 block_articlenew.php 是产生最新文章的,block_articlehot.php是产生热门文章的,看名字就理解差不多了。
为了产生“最新威客任务”,我模仿最新文章
block_articlenew.php 构建了一个新文件(复制一个block_articlenew.php ),名为为block_articleweike.php ,编辑里面的类名和构造函数名,由原来的 block_articlenew替换为block_articleweike,也就是把里面的类名和构造函数名改为和文件名一样的字符(block_articleweike),这个类是继承自文章的基类,所以前面包含了基类的路径“require_once libfile(\'block/article\', \'class\');”
目前,构造函数只从新定义了一个成员函数 $this->setting = array()
我们要改造数据来源,就得重定义另外一个成员函数 function getdata($style, $parameter) 这个在基类里面有定义,我们从基类block_article.php 里面把这个成员函数复制,并把它粘贴到我们新扩展的类 block_articlenew.php 里面,这样我们修改数据来源就不影响其它的扩展类。
这个自行添加的数据来源 block_articlenew.php 就完成了。
我们在打开\\source\\include\\portal\\portal_blockclass.php 为数据来源添加diy显示入口(diy选择文章模块时候,数据来源出现“最新威客任务”下拉选框)
保存,更新缓存,打开你的diy,模块选择文章类,看看,是否是多了个下拉选择?
另,discuz!x的文件命名很有规则,大家看看就有体会了。数组里的key分别对应相关文件。
转自:http://ggmmchou.blog.163.com/blog/static/59333149201142075017844/
|