Factory,顾名思义工厂,这个是加工bean的工厂,bean都存放在./include/modules.php中。
首先在./include/entryPoint.php中加载方法
$current_user = BeanFactory::getBean('Users');
class BeanFactory { ``` public static function getBean($module, $id = null, $params = array(), $deleted = true) { // Check if params is an array, if not use old arguments if (isset($params) && !is_array($params)) { $params = array('encode' => $params); } // Pull values from $params array if (defined('ENTRY_POINT_TYPE') && constant('ENTRY_POINT_TYPE') == 'api') { // In API mode, we can cache all beans unless specifically told not // to retrieve a cached version. $encode = false; $can_cache = isset($params['use_cache']) ? $params['use_cache'] : true; } else { // In GUI mode, we will cache only encoded beans unless specifically // told not to retrieve a cached version. $encode = isset($params['encode']) ? $params['encode'] : true; $can_cache = isset($params['use_cache']) ? $params['use_cache'] && $encode : $encode; } $deleted = isset($params['deleted']) ? $params['deleted'] : $deleted; if (!isset(self::$loadedBeans[$module])) { self::$loadedBeans[$module] = array(); self::$touched[$module] = array(); } $beanClass = self::getBeanName($module); // 如果self:bean_class和modules.php都没发现,到此步就返回null了 if (empty($beanClass) || !class_exists($beanClass)) return null; if (!empty($id)) { if (!$can_cache || empty(self::$loadedBeans[$module][$id])) { // $bean = new $beanClass(); $bean = SugarBean::_createBean($beanClass); // Pro+ versions, to disable team check if we have rights // to change the parent bean, but not the related (e.g. change Account Name of Opportunity) if (!empty($params['disable_row_level_security'])) { $bean->disable_row_level_security = true; } $result = $bean->retrieve($id, $encode, $deleted); if(empty($result)) { if(empty($params['strict_retrieve'])) { return $bean; } else { return null; } } else if ($can_cache) { self::registerBean($bean); } } else { $bean = self::$loadedBeans[$module][$id]; // check if cached bean is deleted if ($deleted && !empty($bean->deleted)) { if(empty($params['strict_retrieve'])) { return SugarBean::_createBean($beanClass); } else { return null; } } // cached bean was retrieved with team security disabled if (empty($params['disable_row_level_security']) && !empty($bean->disable_row_level_security)) { $newBean = SugarBean::_createBean($beanClass); if (isset($params['disable_row_level_security'])) { // false $newBean->disable_row_level_security = false; } if (empty($newBean->disable_row_level_security)) { // retireve with team security enabled $result = $newBean->retrieve($id, $encode, $deleted); if (empty($result)) { if(empty($params['strict_retrieve'])) { return $bean; } else { return null; } } else { // save new bean in cache self::$loadedBeans[$module][$id] = $newBean; return $newBean; } } } self::$hits++; self::$touched[$module][$id]++; } } else { // 到这一步基本上,就是实例化具体的bean类了 $bean = SugarBean::_createBean($beanClass); } return $bean; } // 主要从./include/modules.php中查找是否有该模块 // 如 $beanList['Users'] = 'User'; // $beanFiles['User'] = 'modules/Users/User.php'; public static function getBeanName($module) { if(!empty(self::$bean_classes[$module])) { return self::$bean_classes[$module]; } global $beanList; if (empty($beanList[$module])) { return false; } return $beanList[$module]; } public static function _createBean($beanName) { // 实例化User类 return new $beanName(); } ``` }
class User extends Person { ``` public function User() { self::__construct(); } public function __construct() { parent::__construct(); $this->disable_row_level_security = true; $this->_loadUserPreferencesFocus(); } protected function _loadUserPreferencesFocus() { $this->_userPreferenceFocus = new UserPreference($this); } ``` } // 此类也是继承SugarBean类,而且在实例化时 // 也是要实例化SugarBean,因此只需分析User就可以了,然后这个同理了 class UserPreference extends SugarBean { ``` public function __construct(User $user = null) { parent::__construct(); $this->_userFocus = $user; $this->tracker_visibility = false; } ``` } class Person extends Basic { ``` public function __construct() { parent::__construct(); // 这里是同理的,因为目前这在分析的 // 就是BeanFactory::getBean('Users'); $this->emailAddress = BeanFactory::getBean('EmailAddresses'); } ``` } // 此类实例只是实例化SugarBean的,也就是又回到了SugarBean类了 class Basic extends SugarBean { ``` public function __construct() { parent::__construct(); } ``` }
倒腾一圈,发现又回到了SugarBean的的构造方法了
class SugarBean { public function __construct() { // FIXME: this will be removed, needed for ensuring BeanFactory is always used //$this->checkBacktrace(); // 首次执行构造方法时,这个两全局变量都为空 global $dictionary, $current_user; // 这一步已经在数据库连接时分析过了,返回的当前数据库的实例 $this->db = DBManagerFactory::getInstance(); // 此$this->module_dir是User类的属性,为Users if (empty($this->module_name)) $this->module_name = $this->module_dir; if(isset($this->disable_team_security)){ $this->disable_row_level_security = $this->disable_team_security; } // Verify that current user is not null then do an ACL check. The current user check is to support installation. // 此步不会执行,因为$current_user->id没有 if(!$this->disable_row_level_security && !empty($current_user->id) && (is_admin($current_user) || ($this->bean_implements('ACL') && (ACLAction::getUserAccessLevel($current_user->id,$this->module_dir, 'access') == ACL_ALLOW_ENABLED && (ACLAction::getUserAccessLevel($current_user->id, $this->module_dir, 'admin') == ACL_ALLOW_ADMIN || ACLAction::getUserAccessLevel($current_user->id, $this->module_dir, 'admin') == ACL_ALLOW_ADMIN_DEV))))) { $this->disable_row_level_security =true; } if (false == $this->disable_vardefs && (empty(self::$loadedDefs[$this->object_name]) || !empty($GLOBALS['reload_vardefs']))) { // 不是开发者模式 $refresh = inDeveloperMode() || !empty($_SESSION['developerMode']); if($refresh && !empty(VardefManager::$inReload["{$this->module_dir}:{$this->object_name}"])) { // if we're already reloading this vardef, no need to do it again $refresh = false; } // 主要是加载./cache/modules/Users/uservardefs.php中的字段文件,在$GLOBALS["dictionary"]["User"]数组中 // 此步之后,$dictionary便会有值 VardefManager::loadVardef($this->module_dir, $this->object_name, $refresh, array("bean" => $this)); // build $this->column_fields from the field_defs if they exist // 会执行此步的,因为$GLOBALS["dictionary"]["User"]['fields']有值 if (!empty($dictionary[$this->object_name]['fields'])) { foreach ($dictionary[$this->object_name]['fields'] as $key=>$value_array) { $column_fields[] = $key; if(!empty($value_array['required']) && !empty($value_array['name'])) { $this->required_fields[$value_array['name']] = 1; } } $this->column_fields = $column_fields; } // setup custom fields // 设置自定义字段,如果上面加载的uservardefs.php中 // 没有customer_fields那么就会重新生成个 if(!isset($this->custom_fields) && empty($this->disable_custom_fields)) { $this->setupCustomFields($this->module_dir); } //load up field_arrays from CacheHandler; if(empty($this->list_fields)) $this->list_fields = $this->_loadCachedArray($this->module_dir, $this->object_name, 'list_fields'); if(empty($this->column_fields)) $this->column_fields = $this->_loadCachedArray($this->module_dir, $this->object_name, 'column_fields'); if(empty($this->required_fields)) $this->required_fields = $this->_loadCachedArray($this->module_dir, $this->object_name, 'required_fields'); if(isset($GLOBALS['dictionary'][$this->object_name]) && !$this->disable_vardefs) { $this->field_name_map = $dictionary[$this->object_name]['fields']; $this->field_defs = $dictionary[$this->object_name]['fields']; if (isset($dictionary[$this->object_name]['name_format_map'])) { $this->name_format_map = $dictionary[$this->object_name]['name_format_map']; } if(!empty($dictionary[$this->object_name]['optimistic_locking'])) { $this->optimistic_lock=true; } if (isset($dictionary[$this->object_name]['importable'])) { $this->importable = isTruthy($dictionary[$this->object_name]['importable']); } } self::$loadedDefs[$this->object_name]['column_fields'] =& $this->column_fields; self::$loadedDefs[$this->object_name]['list_fields'] =& $this->list_fields; self::$loadedDefs[$this->object_name]['required_fields'] =& $this->required_fields; self::$loadedDefs[$this->object_name]['field_name_map'] =& $this->field_name_map; self::$loadedDefs[$this->object_name]['field_defs'] =& $this->field_defs; self::$loadedDefs[$this->object_name]['name_format_map'] =& $this->name_format_map; } else { $this->column_fields =& self::$loadedDefs[$this->object_name]['column_fields'] ; $this->list_fields =& self::$loadedDefs[$this->object_name]['list_fields']; $this->required_fields =& self::$loadedDefs[$this->object_name]['required_fields']; $this->field_name_map =& self::$loadedDefs[$this->object_name]['field_name_map']; $this->field_defs =& self::$loadedDefs[$this->object_name]['field_defs']; $this->name_format_map =& self::$loadedDefs[$this->object_name]['name_format_map']; $this->added_custom_field_defs = true; if(!isset($this->custom_fields) && empty($this->disable_custom_fields)) { $this->setupCustomFields($this->module_dir, false); } if(!empty($dictionary[$this->object_name]['optimistic_locking'])) { $this->optimistic_lock=true; } } // Verify that current user is not null then do an ACL check. The current user check is to support installation. if(!$this->disable_row_level_security && !empty($current_user->id) && !isset($this->disable_team_security) && !SugarACL::checkAccess($this->module_dir, 'team_security', array('bean' => $this))) { // We can disable team security for this module $this->disable_row_level_security =true; } if($this->bean_implements('ACL')){ $this->acl_fields = (isset($dictionary[$this->object_name]['acl_fields']) && $dictionary[$this->object_name]['acl_fields'] === false)?false:true; if (!empty($current_user->id)) { ACLField::loadUserFields($this->module_dir,$this->object_name, $current_user->id); } $this->addVisibilityStrategy("ACLVisibility"); } $this->populateDefaultValues(); if(isset($this->disable_team_security)){ $this->disable_row_level_security = $this->disable_team_security; } } function setupCustomFields($module_name, $clean_load=true) { if (empty($module_name)) { // No need to load every single dynamic field here return; } $this->custom_fields = new DynamicField($module_name); $this->custom_fields->setup($this); } ``` }