资源探测器

资源探测器是什么?

在Ecos系统里, 每个APP会有很多的资源, 例如:service.xml, dbschema定义文件, site.xml等. 系统支持的资源会在APP进行安装 更新 卸载 暂停 启用时, 进行相应的安装,卸载等相应的资源.

Ecos对于资源的识别和管理, 是通过资源探测器来完成的.

两种类型的资源探测器

  • xml文件资源探测器, 例如: app.xml, services.xml.
  • 目录资源探测器, 例如: dbschema定义目录, 语言包等

系统里都有什么资源探测器

系统里会内置多个核心的资源

  • 数据库定义目录资源探测器-base_application_dbtable 关注dbschema
  • service资源探测器-base_application_service 关注services.xml
  • 语言包资源探测器-base_application_lang
  • 缓存更新探测器-base_application_cache_expires

其余的资源探测器, 都通过service的形式进行注册, 注册点为app_content_detctor

先来看看系统里目前已注册的资源探测器

./cmd dev:show services | grep -i app_content_detector

资源探测器开发

资源探测器基类


base_application_prototype_xml(xml文件资源探测器)类提供了可以遍历xml文件下某个节点下所有子节点的接口

base_application_prototype_filepath(目录资源探测器)类提供了可以遍历目录里所有文件或目录的接口

补充知识:

如果你希望支持其他类型的资源探测器,需要你自己进行扩展了.
开发需要预先学习[Iterator http://cn.php.net/manual/cn/class.iterator.php]
然后参考一下base_application_prototype_xml类和base_application_prototype_filepath类

因为最底层的基类implements Iterator, 所以对于Iterator, 还是要有个基本的了解

如何开发xml文件资源探测器

这里拿desktop app的后台权限探测器做个例子. 后台菜单探测器针对的是desktop.xml内寻取permissions下的所有pemission子节点.

建立类文件

首先要确认用哪种类型的探测器. 在本例中, 是针对xml类型的文件, 因此...

补充知识:

资源探测器存放的位置, 按照管理放在app/{$app_id}/lib/application目录下
<?php
class desktop_application_permission extends base_application_prototype_xml {
      ...
}


文件位置: app/desktop/lib/application/permission.php

注册成service

首先需要在service中进行注册, 在desktop app中有一组针对desktop.xml的探测器.

app/desktop/desktop.xml

<services>
   ...
   <service id="app_content_detector">
        <class>desktop_application_permission</class>   
        <class>desktop_application_menu</class>
        <class>desktop_application_workground</class>
        <class>desktop_application_panelgroup</class>
        <class>desktop_application_adminpanel</class>
        <class>desktop_application_theme</class>
        <class>desktop_application_widgets</class>
    </service>
    ...
</services>

确认所关注的xml资源和节点

这里会用到 $xml, $xsd, $path
<?php
class desktop_application_permission extends base_application_prototype_xml {

    var 
$xml='desktop.xml'//指定关注的xml资源, 本例中会调取app/desktop/desktop.xml, 本属性支持路径, 例如: 'abc/kkk.xml'
    
var $xsd='desktop_content'//指定xml对应的xsd位置, 本例中为 app/desktop/xmlschema/content.xsd
    
var $path 'permissions/permission'//设定关注的xml的节点, 采用xpath的方式获取. 本例中意味着会在desktop.xml寻取permissions下的所有pemission子节点.
    
...
}

编写回调函数

current

设置当前遍历子节点的内容($current)和当前元素的键($key)

通过$this->iterator()->current(), 可以获得当前xml子节点的array数据.

在本例中$this->iterator()->current()返回的是遍历到的当前permissions/permission/节点数据.

<?php
class desktop_application_permission extends base_application_prototype_xml {

    ...
    function 
current(){
        
$this->current $this->iterator()->current();
        
$this->key $this->current['id'];
        return 
$this;
    }
    ...
install

资源安装, 在app install时会调用

需要重载

安装当前遍历节点的数据

<?php
class desktop_application_permission extends base_application_prototype_xml {
    ...
    function 
install(){    
        
kernel::log('Installing '.$this->content_typename().' '.$this->key());
        return 
app::get('desktop')->model('menus')->insert($this->row());
    }

    function 
row(){
        
$row = array(
            
'menu_type' => $this->content_typename(),
            
'app_id'=>$this->target_app->app_id,
                );
        
$row['menu_title'] = $this->current['value'];
        
$row['display'] =  $this->current['display'];
        
$access_opct = array(
            
'show' => $this->current['show'],
            
'save' => $this->current['save'],
                );
        
$row['addon'] = serialize($access_opct);
        
$row['permission'] = $this->current['id']; 
        return 
$row;
    }
    ...
    
clear_by_app

资源卸载, 在app uninstall时会调用

<?php
class desktop_application_permission extends base_application_prototype_xml {
    function 
clear_by_app($app_id){
        if(!
$app_id){
            return 
false;
        }
        
app::get('desktop')->model('menus')->delete(array(
            
'app_id'=>$app_id,'menu_type' => $this->content_typename()));
    }
update

资源更新, 在app update时会调用

update所有节点, 在基类中的实现会遍历所有节点, 然后对每个节点进行install通常不需要重载

active_by_app

资源卸载, 在app active时会调用

通常不需要重载

pause_by_app

资源暂停, 在app pause时会调用

如果不重载此函数, 默认的情况是调用clear_by_app

通常不需要重载

如何开发目录型资源探测器

和开发xml文件资源探测器的方式基本一致,区别在于:

  • 去掉了$xml和$xsd属性. $path路径用来标识关注的目录, 目录支持路径
  • 增加了filter()函数, 可以只遍历$path目录下关注的文件和目录
  • current()函数无需重载, 基类提供的函数默认设置$key为文件名/目录名
  • 增加getPathname()函数, 可以取得当前节点的目录名
  • 增加getFilename()函数, 可以取得当前节点的文件名

可以参考: site_application_widgets类