本帖最后由 元首 于 2009-6-7 21:07 编辑
discuz的后台拥有着非常变态的实现过程, 即没有html文件, 全部的实现都靠几个函数来完成,当然这种结构下就促使了它的后台单一化,及极其难修改. 整体来说过程是非常清晰的, 仅仅用了几个通用函数就解决了这一页页的后台管理.
现在我们开始分析.
admincp.php文件:- <?php
- /*
- [Discuz!] (C)2001-2009 Comsenz Inc.
- This is NOT a freeware, use is subject to license terms
- $Id: admincp.php 16688 2008-11-14 06:41:07Z cnteacher $
- */
- define('IN_ADMINCP', TRUE);
- define('NOROBOT', TRUE);
- require_once './include/common.inc.php';
- //加载后台函数
- require_once DISCUZ_ROOT.'./admin/global.func.php';
- //加载管理员类库
- require_once DISCUZ_ROOT.'./admin/cpanel.share.php';
- //加载缓存系统.
- require_once DISCUZ_ROOT.'./include/cache.func.php';
- //加载语言模块
- include language('admincp');
- //设置当前动作
- $discuz_action = 211;
- //取得当前IP
- $admincp['checkip'] && $onlineip = empty($_SERVER['REMOTE_ADDR']) ? getenv('REMOTE_ADDR') : $_SERVER['REMOTE_ADDR'];
- //开始更新管理员记录
- $adminsession = new AdminSession($discuz_uid, $groupid, $adminid, $onlineip);
- //取得管理员记录.
- $dactionarray = $adminsession->get('dactionarray');
- //判断.
- if($dactionarray === null) {
- $dactionarray = array();
- if($radminid != $groupid) {
- $tmp = unserialize($db->result_first("SELECT disabledactions FROM {$tablepre}adminactions WHERE admingid='$groupid'"));
- $dactionarray = $tmp ? $tmp : array();
- }
- $adminsession->set('dactionarray', $dactionarray, true);
- }
- //如果会员ID不是管理员,就为0, 如果是管理员, 就为1, 如果已经登录,就为2
- $cpaccess = $adminsession->cpaccess;
- //如果标识为0 即前台会员未登录,或者管理员ID不正确, 就进入登录页.
- if($cpaccess == 0 || (!$discuz_secques && $admincp['forcesecques'])) {
- require_once DISCUZ_ROOT.'./admin/login.inc.php';
- } elseif($cpaccess == 1) {
- //当$admin_password不为空, 就登录.
- if($admin_password != '') {
- require_once DISCUZ_ROOT.'./uc_client/client.php';
- $ucresult = uc_user_login($discuz_uid, $admin_password, 1, 1, $admin_questionid, $admin_answer); //uc的接口.
- if($ucresult[0] > 0) {
- $adminsession->errorcount = -1;
- $adminsession->update();
- dheader('Location: '.$BASESCRIPT.'?'.cpurl('url', array('sid'))); //直接用跳转.
- } else {
- $adminsession->errorcount ++;
- $adminsession->update();
- writelog('cplog', dhtmlspecialchars("$timestamp\t$discuz_userss\t$adminid\t$onlineip\t$action\tAUTHENTIFICATION(PASSWORD)"));
- }
- }
- //如果上而代码没有跳转, 那又回到登录页.
- require_once DISCUZ_ROOT.'./admin/login.inc.php';
- } else {
- //$cpaccess为2了.
- //处理管理员用户名
- $username = !empty($username) ? dhtmlspecialchars($username) : '';
- //处理GET
- $action = !empty($action) && is_string($action) ? trim($action) : '';
- $operation = !empty($operation) && is_string($operation) ? trim($operation) : '';
- $page = isset($page) ? intval((max(1, $page))) : 0;
- //处理两个动作.
- if(!empty($action) && !in_array($action, array('main', 'logs'))) {
- switch($cpaccess) {
- case 1:
- $extralog = 'AUTHENTIFICATION(ERROR #'.intval($adminsession['errorcount']).')';
- break;
- case 3:
- $extralog = implodearray(array('GET' => $_GET, 'POST' => $_POST), array('formhash', 'submit', 'addsubmit', 'admin_password', 'sid', 'action'));
- break;
- default:
- $extralog = '';
- }
- $extralog = trim(str_replace(array('GET={};', 'POST={};'), '', $extralog));
- $extralog = (($action == 'home' && isset($securyservice)) || ($action == 'insenz' && in_array($operation, array('register', 'binding')))) ? '' : $extralog;
- writelog('cplog', implode("\t", clearlogstring(array($timestamp,$discuz_userss,$adminid,$onlineip,$action,$extralog))));
- unset($extralog);
- }
- $isfounder = $adminsession->isfounder = isfounder();
- if(empty($action) || isset($frames)) {
- //管理页的首页.
- $extra = cpurl('url');
- $extra = $extra && $action ? $extra : (!empty($runwizard) ? 'action=runwizard' : 'action=home');
- require_once DISCUZ_ROOT.'./admin/main.inc.php';
- } elseif($action == 'logout') {
- //退出动作.
- $adminsession ->destroy();
- dheader("Location: $indexname");
- } else {
- //更新当前动作.
- checkacpaction($action, $operation);
- //这句有意思了, action来引入某个执行文件. 关键点.
- if(in_array($action, array('home', 'settings', 'members', 'profilefields', 'admingroups', 'usergroups', 'ranks', 'forums', 'threadtypes', 'threads', 'moderate', 'attach', 'smilies', 'recyclebin', 'prune', 'styles', 'plugins', 'tasks', 'magics', 'medals', 'google', 'qihoo', 'video', 'announce', 'faq', 'ec', 'tradelog', 'creditwizard', 'jswizard', 'project', 'counter', 'misc', 'adv', 'insenz', 'logs', 'tools', 'checktools', 'search', 'upgrade')) || ($isfounder && in_array($action, array('runwizard', 'templates', 'db')))) {
- require_once DISCUZ_ROOT.'./admin/'.$action.'.inc.php'; // 引入.
- $title = 'cplog_'.$action.($operation ? '_'.$operation : '');
- if(!in_array($action, array('home', 'custommenu')) && lang($title, false)) {
- (strtolower($_SERVER['REQUEST_METHOD']) == 'get') && admincustom($title, cpurl('url'));
- }
- } else {
- cpheader();
- cpmsg('noaccess');
- }
- //结束函数.
- cpfooter();
- }
- }
- ?>
复制代码 我们依后台管理的全局为例子, 来新建立一个管理页面..- if(in_array($action, array('home', 'settings', 'members', 'profilefields', 'admingroups', 'usergroups', 'ranks', 'forums', 'threadtypes', 'threads', 'moderate', 'attach', 'smilies', 'recyclebin', 'prune', 'styles', 'plugins', 'tasks', 'magics', 'medals', 'google', 'qihoo', 'video', 'announce', 'faq', 'ec', 'tradelog', 'creditwizard', 'jswizard', 'project', 'counter', 'misc', 'adv', 'insenz', 'logs', 'tools', 'checktools', 'search', 'upgrade')) || ($isfounder && in_array($action, array('runwizard', 'templates', 'db')))) {
- require_once DISCUZ_ROOT.'./admin/'.$action.'.inc.php'; // 引入.
- //全局的标识是: settings 所以我们会引入settings.inc.php文件. 此文件在admin目录中.
复制代码 标识在哪里修改呢?? 在admin目录中menu.inc.php文件中.
似乎里面写的全是代码,没有中文, 能够问这个问题, 你可以先看看templates/default/admincp.lang.php语言文件.
首先我们打开:menu.inc.php文件
查找:- showmenu('global', array(
复制代码 在它的下一行增加:- array('menu_settings_function, 'settings&operation=function'),
复制代码 接着,我们需要修改一下语言文件admincp.menu.lang.php让它显示出我们想要的管理页名称.
查找:- 'menu_settings_basic' => '站点信息',
复制代码 在它的上一行增加:- 'menu_settings_function' => '分享工作室',
复制代码 现在刷新一下, 左边是不是显示了一个新的页链接? 分享工作室?
接着, 我们需要定义一下链接显示页的标题:打开admincp.lang.php文件
查找:- 'settings_basic' => '站点信息',
复制代码 在它的上一行增加:- 'settings_function'=>'新增加管理页',
复制代码 似乎现在可以点击,但内容显示为未定义操作。, 那么我们要怎么让程序来运行新的动作呢? 接着我们打开 settings.inc.php,查找:- cpmsg('undefined_action');
复制代码 这个函数位于动作判断的最后一个默认输出, 即前面没有符全项目, 就进入这个函数输出.为此,我们增加一个条件判断:写在else前面..- elseif ($operation === 'function'){
- echo '我是新符合条件的管理页';
- }
复制代码 再点击一下链接,完美了, 结果就是这样:
|