SugarCRM源码分析之ViewFactory
2016-01-27 14:05
204 查看
和ControllerFactory类似,ViewFactory则负责实例并初始各个模块的视图类,不过调用的视图工厂则是在各个具体控制器内。
下面接主要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域名,会加载配置文件中的默认模块和默认方法)
继承了SideView类,初始化时设置了页面属性并加载父类SidecarView初始化方法
SidecarView又继承了SugarView类,同时也在初始化时执行了父类SugarView类的__construct方法
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']); } ``` }
相关文章推荐
- opencart mail服务器的配置
- ServerStatus 输出说明
- swift中单例的实现方法
- Ubuntu 14.04 64位使用Google字体(英文、中文分别修改)
- C++类中成员变量和成员指针变量小结
- python的thread使用
- Spring RMI调用远程方法
- 算法题2 动态规划之最大子序列和&最大子矩阵和
- HDU 1033 Edge
- MSSQL STUFF
- 广州易幻网络科技有限公司Android笔面经 (未通过)
- 配置xheditor图片上传功能
- SpringMVC 和 Struts2 框架区别
- Unity5.3.1f1 Network 局域网实时联网demo
- HttpClient和HttpURLConnection的区别
- 关于python使用MySQLdb新增操作
- 前端工程师使用node.js打造日记社区教程之一
- Android学习----自适应国际化语言
- web移动端常见问题总结
- wdatepicker,自定义时间限制