SugarCRM源码分析之BeanFactory


        Factory,顾名思义工厂,这个是加工bean的工厂,bean都存放在./include/modules.php中。


        首先在./include/entryPoint.php中加载方法

$current_user = BeanFactory::getBean('Users');

        其次,进入到BeanFactory中的静态类getBean执行

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();
    }
    ```

}

        那么接下来看看User类中的逻辑吧

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);

    }
    ```

}


你可能感兴趣的:(SugarCRM源码分析之BeanFactory)