SugarCRM源码分析之ViewFactory


        和ControllerFactory类似,ViewFactory则负责实例并初始各个模块的视图类,不过调用的视图工厂则是在各个具体控制器内。

class SugarController
{
    ```
    private function processView(){
        if(!isset($this->view_object_map['remap_action']) && isset($this->action_view_map[strtolower($this->action)]))
        {
          $this->view_object_map['remap_action'] = $this->action_view_map[strtolower($this->action)];
        }
        $view = ViewFactory::loadView($this->view, $this->module, $this->bean, $this->view_object_map, $this->target_module);
        $GLOBALS['current_view'] = $view;
        if(!empty($this->bean) && !$this->bean->ACLAccess($view->type) && $view->type != 'list'){
            ACLController::displayNoAccess(true);
            sugar_cleanup(true);
        }
        if(isset($this->errors)){
          $view->errors = $this->errors;
        }
        $view->process();
    }
    ```
}

        下面接主要ViewFactory的功能

class ViewFactory
{

    /**
     * load the correct view
     * @param string $type View Type
     * @return valid view
     */
    function loadView($type = 'default', $module, $bean = null, $view_object_map = array(), $target_module=''){
        $type = strtolower($type);

        // first let's check if the module handles this view

        $view = null;

        // Check to see if we should load a custom parent view instance
        /**
          * 这一步加载具体的视图类【ViewSidecar】文件,并且进而引入试图类【SidecarView】,最后引入总的视图继承类
          * class ViewSidecar extends SidecarView {```}
          * class SidecarView extends SugarView {```}
          * class SugarView {```}
            function loadParentView($type)
            {
                SugarAutoLoader::requireWithCustom('include/MVC/View/views/view.'.$type.'.php');
            }
        */
        loadParentView($type);

        if(!empty($target_module)) {
            $view_file = SugarAutoLoader::existingCustomOne('modules/'.$target_module.'/views/view.'.$type.'.php');
            $view_module = $target_module;
        } else {
            $view_module = $module;
        }

        // 下面三步,逐次提高,现在所属模块查找view文件,没有再提升到总的视图查找
        // 这里侧重的是如果用户定制了视图文件,那么就加载用户定制的视图文件
        // 因为existingCustomOne最后加载的视图文件[如果有的话],返回时array_pop会把此文件给弹出来
        if(empty($view_file)) {
            $view_file = SugarAutoLoader::existingCustomOne('modules/'.$module.'/views/view.'.$type.'.php');
        }
        if(empty($view_file)) {
            $view_file = SugarAutoLoader::existingCustomOne('include/MVC/View/views/view.'.$type.'.php');
        }
        if(!empty($view_file)) {
            $view = ViewFactory::_buildFromFile($view_file, $bean, $view_object_map, $type, $view_module);
        }

        if(empty($view)) {
            // Default to SugarView if still nothing found/built
            $view = new SugarView();
        }

        ViewFactory::_loadConfig($view, $type);
        return $view;
    }

    /**
     * This is a private function which just helps the getView function generate the
     * proper view object
     *
     * @return a valid SugarView
     */
    function _buildFromFile($file, &$bean, $view_object_map, $type, $module){

        // 第一优先级,查找HomeViewSidecar类
        require_once($file);
        //try ModuleViewType first then try ViewType if that fails then use SugarView
        $class = SugarAutoLoader::customClass(ucfirst($module).'View'.ucfirst($type));

        if(class_exists($class)){
            return ViewFactory::_buildClass($class, $bean, $view_object_map);
        }

        // 第二优先级,查找ViewSidecar类,bingo
        //Now try the next set of possibilites if it was none of the above
        //It can be expensive to load classes this way so it's not recommended
        $class = SugarAutoLoader::customClass('View'.ucfirst($type));
        if(class_exists($class)){
            return ViewFactory::_buildClass($class, $bean, $view_object_map);
        }

         // 第三优先级,查找SugarView类
        //Now check if there is a custom SugarView for generic handling
        // autoloader will check filesystem
        $class = SugarAutoLoader::customClass('SugarView', true);
        //if all else fails return SugarView
        return new $class($bean, $view_object_map);

    }

    /**
     * instantiate the correct view and call init to pass on any obejcts we need to
     * from the controller.
     *
     * @param string class - the name of the class to instantiate
     * @param object bean = the bean to pass to the view
     * @param array view_object_map - the array which holds obejcts to pass between the
     *                                controller and the view.
     *
     * @return SugarView
     */
    function _buildClass($class, $bean, $view_object_map){

        // 实例并初始化
        $view = new $class();
        $view->init($bean, $view_object_map);
        if($view instanceof SugarView){
            return $view;
        }else
            return new SugarView($bean, $view_object_map);
    }

    /**
     * Load the view_<view>_config.php file which holds options used by the view.
     */
    function _loadConfig(&$view, $type){
        $view_config_custom = array();
        $view_config_module = array();
        $view_config_root_cstm = array();
        $view_config_root = array();
        $view_config_app = array();
        $config_file_name = 'view.'.$type.'.config.php';
        $view_config = sugar_cache_retrieve("VIEW_CONFIG_FILE_".$view->module."_TYPE_".$type);
        if(!$view_config){
            $view_config_all = array('actions' => array(), 'req_params' => array(),);

            // 加载include/MVC/View/views/view.config.php后,$view_config会有数据
            foreach(SugarAutoLoader::existingCustom(
                'include/MVC/View/views/view.config.php',
                'include/MVC/View/views/'.$config_file_name,
                'modules/'.$view->module.'/views/'.$config_file_name
            ) as $file) {
                $view_config = array();
                require $file;
                if(!empty($view_config['actions'])) {
                    $view_config_all['actions'] = array_merge($view_config_all['actions'], $view_config['actions']);
                }
                if(!empty($view_config['req_params'])) {
                    $view_config_all['req_params'] = array_merge($view_config_all['req_params'], $view_config['req_params']);
                }
            }
            $view_config = $view_config_all;

            sugar_cache_put("VIEW_CONFIG_FILE_".$view->module."_TYPE_".$type, $view_config);
        }
        $action = strtolower($view->action);
        $config = null;
        if(!empty($view_config['req_params'])){
            // try the params first
            foreach($view_config['req_params'] as $key => $value){
                if(!empty($_REQUEST[$key]) && $_REQUEST[$key] == "false") {
                    $_REQUEST[$key] = false;
                }
                if(!empty($_REQUEST[$key])){

                    if(!is_array($value['param_value'])){
                        if($value['param_value'] ==  $_REQUEST[$key]){
                            $config = $value['config'];
                            break;
                        }
                    }else{

                        foreach($value['param_value'] as $v){
                            if($v ==  $_REQUEST[$key]){
                                $config = $value['config'];
                                break;
                            }

                        }
                    }
                }
            }
        }
        if($config == null && !empty($view_config['actions']) && !empty($view_config['actions'][$action])){
                $config = $view_config['actions'][$action];
        }
        if($config != null)
            $view->options = $config;
    }

}


        拿实例化ViewSidecar类来说(这个是按默认的模块来的,也就是直接输入本地SugarCRM域名,会加载配置文件中的默认模块和默认方法)

require_once('include/MVC/View/SidecarView.php');

class ViewSidecar extends SidecarView
{
    /**
     * Constructor
     *
     * @see SidecarView::SidecarView()
     */
 	public function __construct($bean = null, $view_object_map = array())
 	{
        $this->options['show_title'] = false;
        $this->options['show_header'] = false;
        $this->options['show_footer'] = false;
        $this->options['show_javascript'] = false;
        $this->options['show_subpanels'] = false;
        $this->options['show_search'] = false;
 		parent::__construct($bean = null, $view_object_map = array());
 	}

}

        继承了SideView类,初始化时设置了页面属性并加载父类SidecarView初始化方法

class SidecarView extends SugarView
{
    ```
    protected $configFileName = "config.js";
    protected $configFile;
    
    public function __construct()
    {
        $this->configFile = sugar_cached($this->configFileName);
        parent::SugarView();
    }
    ```
}

      SidecarView又继承了SugarView类,同时也在初始化时执行了父类SugarView类的__construct方法

class SugarView
{

    ```

    /**
     * Constructor which will peform the setup.
     */
    public function SugarView($bean = null, $view_object_map = array())
    {
        $this->base_menu = SugarAutoLoader::loadExtension("menus", "application");
    }

    public function init($bean = null, $view_object_map = array())
    {
        $this->bean = $bean;
        $this->view_object_map = $view_object_map;
        $this->action = $GLOBALS['action'];
        $this->module = $GLOBALS['module'];
        $this->_initSmarty();
    }

    // 加载smarty模板类
    protected function _initSmarty()
    {
        $this->ss = new Sugar_Smarty();
        $this->ss->assign('MOD', $GLOBALS['mod_strings']);
        $this->ss->assign('APP', $GLOBALS['app_strings']);
    }

    ```

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值