一、界面中采用的技术
页面编写采用php动态语言,并且采用smarty框架,将数据与页面显示分离开来。
比如/var/www/html/modules/pbxadmin/themes/main.tpl模板。
$smarty->assign("Option", _tr('Option'));第一个Option是参数名称,第二个是把内容替换到模板相应的参数位置。
二、界面加载概要过程
/var/www/html/index.php页面分为两个部分,头部菜单(一级及二级菜单)和中间内容部分(content部分)。/var/www/html/index.php是主页面,所有的模块都会把自己的内容动态添加到content部分。
三、实例说明页面加载详细过程
首次等于网站,进入默认的菜单项的界面,这个过程和点击某个菜单加载是一致的。
Pbx下配置的Extension页面加载说明
选择pbx一级菜单下的配置二级菜单,这时候发现页面跳入了extension的界面,这是个默认界面,如果我们点击内容部分左边的菜单extension,这时候页面重新加载到这个界面,这个流程详细说明一下。
- 点击pbx下的配置,加载pbx配置模块界面。
菜单超链接为/index.php?menu=pbxconfig,链接中携带的menu参数信息,
这里的index.php为var/www/html/index.php文件。在该文件中可看到如下代码:
$menu=$_GET['menu'];
$oPn->showMenu($menu);//加载页面的最上方的menu部分,并且将当前menu告知oPn对象,以加载对应menu下的内容,如果menu为空,则加载默认的menu下的内容。
$smarty->assign("CONTENT", $oPn->showContent());//$oPn->showContent()根据当前menu获取内容,将内容赋值到smarty模板中(值得注意的地方是主页面的模板在/var/www/html/themes/elastixwine/_common/index.tpl为模板的位置)。
- $oPn->showContent()函数的执行过程。
$oPn初始化的代码
$oPn = new paloSantoNavigation($arrConf, $arrMenuFiltered, $smarty);
paloSantoNavigation该类主要是对一些 menu 操作的封装,包括获取菜单、显示菜单、内容显示、获取服务器名、获取服务器 IP等
paloSantoNavigation类在libs/paloSantoNavigation.class.php文件中定义声明。$arrConf,没有什么作用,整个 menu 数组存储在 $arrMenuFiltered 数组中,包括父菜单和子菜单,这个是生成头部的所有menu的数据。
showContent()方法内部,根据当前的menu查找所属模块,之后方法内部调用includeModule($module),这个方法作用是动态调用/var/www/html/modules/pbxadmin/index.php(这里以pbxadmin举例)中的_moduleContent(&$smarty, $module_name)方法,_moduleContent方法就是加载具体模块界面内容。
if(isset($_REQUEST['display'])) {
$display = $_REQUEST['display'];
} else {
$display = 'extensions';
$_REQUEST['display'] = 'extensions';
}
Display可能会附属在href参数位置,默认为extentions分机,这里先解释几个名词的意思
display:模块左边菜单的名称,比如extensions,featureAdmin等。
Extdisplay:分机或者叫设备名称
type:display下的页面可能是编辑可能是添加,主要区分这些界面,展现由功能决定,$currentcomponent = new component($display,$type);type传入到component类中,不同的type生成不同的界面。Component的作用是组合界面。
action:操作的命令,有add,del, edit, resetall,比如add是添加一个分机设备,这个可以在/var/www/html/admin/modules/core/functions,inc.php
找到相应的内容(最下面)。
还有一些其他的会传过来的参数,和具体的操作都有关系。
程序中判断所有的这些参数,根据值加载不同的内容页面。比如上述的$_REQUEST['display'] = 'extensions'; $type = isset($_REQUEST['type'])?$_REQUEST['type']:'setup';
刚进入pdxconfig配置界面,默认的为
'extensions' 的type为set up界面(set up就是添加功能界面)。
- extension的界面type为set up界面是如何生成的,下面开始解释这个过程。
foreach($active_modules as $key => $module) {
if(is_file("/var/www/html/admin/modules/{$key}/functions.inc.php" )) { require_once("/var/www/html/admin/modules/{$key}/functions.inc.php");
其中$active_modules是所有asterisk平台可用的模块集合,
$active_modules = module_getinfo(false, MODULE_STATUS_ENABLED,true);由这个pdxadmin/index.php函数module_getinfo得到,/var/www/html/admin/modules/目录下的所有模块信息。module_getinfo()定义在var/www/html/admin /functions.inc.php文件中,研究module_getinfo()函数我们得知它是读取/var/www/html/admin/modules/目录下文件夹名称作为key值,
读取modulelist,如果强制加载会读取每个模块下的module.xml文件,这个文件记录模块包含哪几个功能块,比如core模块包含了extenstions。如果不强制加载则读取数据库中module表数据。最后$active_modules数组。
Foreach循环中会循环执行require_once("/var/www/html/admin/modules/{$key}/functions.inc.php”);加载这样的文件。比如pdxadmin模块的名称为core,加载名称为
/var/www/html/admin/modules/core/functions.inc.php。这个文件提供了extension页面的显示内容。
接下来识别哪些模块是有权限访问的,同时找出当前的pdxadmin的菜单项(以pdxadmin举例说明),
if ($display == $item['display']) { //找出当前的菜单项
$cur_menuitem =& $fpbx_menu[$itemKey];
}
下一步找出模块中的初试化的函数
foreach($active_modules as $key => $module) {
if (isset($module['items']) && is_array($module['items'])) {
foreach($module['items'] as $itemKey => $itemName) {
//list of potential _configpageinit functions
$initfuncname = $key . '_' . $itemKey . '_configpageinit'; if ( function_exists($initfuncname) ) {
$configpageinits[] = $initfuncname;
}
}
}
//check for module level (rather than item as above) _configpageinit function
$initfuncname = $key . '_configpageinit';
if ( function_exists($initfuncname) ) {
$configpageinits[] = $initfuncname;
}
}
}
$initfuncname的值会是:
voicemail_configpageinit,ringgroups_configpageinit,core_agent_configpageinit,
core_users_configpageinit,core_devices_configpageinit等函数名称。其中有些函数名是不存在的,比如voicemail_configpageinit,ringgroups_configpageinit等,这些configpageinit作用是初始化好界面的内容,即实现组装好界面的流程。这些函数存在的位置为/var/www/html/admin/modules/{$key}/functions.inc.php
文件中如果没有对应的函数的话说明不存在,extension是存在的key为core。
$currentcomponent->processconfigpage();//在前面的$configpageinits已经初始化界面数据但是还没有执行,在这里调用processconfigpage函数
$currentcomponent->buildconfigpage();//这里的主要作用是根据配置文件转化语言。
if ( isset($currentcomponent) ) {
echo $currentcomponent->generateconfigpage();//生成html界面
}
$htmlFPBX .= @ob_get_contents();//将模块显示内容赋值给$htmlFPBX
- 点击事件是如何触发的
在extension界面中,提交添加的分机信息,提交给/index.php,post方式提交,携带action=add,还有menu,display,type、填写的内容等信息,由于提交的是/index.php,此页面会根据上面的流程重新加载到当前界面,action为add会执行
//if submitting form, update database
switch ($action) {
case "add":
// really bad hack - but if core_users_add fails, want to stop core_devices_add
if (!isset($GLOBALS['abort']) || $GLOBALS['abort'] !== true || !$_SESSION["AMP_user"]->checkSection('999')) {
if(core_devices_add($deviceid,$tech,$devinfo_dial,$devicetype,$deviceuser,$description,$emergency_cid)) {
……….
这段代码在admin/modules/core/function.inc.php文件的最下方。
同理编辑界面action为edit也会执行这边。
core_devices_add方法在当前文件中,action的操作只会将数据存入到mysql数据库中,这时候不会写入到配置文件中去。
- Handler=reload的执行过程
case 'reload':
include_once('/var/www/html/admin/common/json.inc.php');
$response = do_reload();
$json = new Services_JSON();
//echo $json->encode($response);
break;
最主要调用do_reload()方法,这个方法在/var/www/html/admin/index.php中声明,do_reload()是如何执行的
大致过程就是先执行命令
$retrieve = $amp_conf['AMPBIN'].'/retrieve_conf 2>&1';
exec($retrieve, $output, $exit_val);
执行var/lib/asterisk/bin/retrieve_conf文件,其实它就是一个php文件,从数据库中读取数据写到相应的配置文件中,core模块的数据信息在var/www/html/admin/modules/coe/functions.lnc.php, get_filename()方法是读取配置文件的名称,generateConf($file)是各个配置文件的数据。
数据写入配置文件,还没有完成,因为没有将配置文件数据加载到
内存中即配置文件没有生效,所以do_reload()接下来发送命令
//reload MOH to get around 'reload' not actually doing that.
$astman->send_request('Command', array('Command'=>'moh reload'));
//reload asterisk
$astman->send_request('Command', array('Command'=>'reload'));
第一条不知道是什么意思,说不定是语音呢,第二条为配置文件重新加载到内存。
四、 特别解释的地方
- Asterisk 具有内部数据库,astdb,这个数据库的主要提供了一个简单的方式,用来存储拨号方案的数据。主要通过命令来实现
Action: Command
Command: database put AMPUSER 8008/password ""
存入到内部数据库中,下次读取的时候,从这里读取,可以参见博客
http://blog.csdn.net/jianghao616/article/details/6134188。
当我们存储数据到内部数据库中,配置文件很容易读取到值。
- 修改配置文件
当我们在界面上修改了一些配置数据,保存,此时并没有生效。
界面会出现提示我们需要重新加载配置项,这个的含义是想把保存在mysql数据库的数据重新写到配置文件中,同时重新加载配置文件,使得asterisk能够将这些数据加载到内存中。