/** * @return AOP */ public function registerBean(array $arrConfig, $sAspectDefineFile = null) { if (empty($arrConfig['class'])) { $arrConfig['class'] = 'aspect'; } $aAspect = BeanFactory::singleton()->createBean($arrConfig); if ($sAspectDefineFile) { $aAspect->setAspectFilepath(FSO::tidyPath($sAspectDefineFile)); } $this->aspects()->add($aAspect); $this->aPointcutIterator = null; $this->aJointPointIterator = null; return $this; }
/** * @wiki /MVC模式/控制器/网页框架(frame) * ==Bean配置数组== * {| * !属性 * !类型 * !默认值 * !可选 * !说明 * |-- -- * |frameviews * |array * |无 * |可选 * |子框体视图 * |} */ public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { $aBeanFactory = BeanFactory::singleton(); $aModelContainer = $this->modelContainer(); foreach ($arrConfig as $sKey => &$item) { // 将 frameView:xxxx 转换成 frameViews[] 结构 if (strpos($sKey, 'frameview:') === 0) { $sName = substr($sKey, 10); if (!is_array($item)) { throw new BeanConfException("视图Bean配置的 %s 必须是一个数组", $sKey); } $arrConfig['frameviews'][$sName] =& $item; } else { if ($sKey == 'frameview') { $arrConfig['frameviews']['frameview'] =& $arrConfig[$sKey]; } } } // frameViews -------------------- if (!empty($arrConfig['frameviews'])) { foreach ($arrConfig['frameviews'] as $key => &$arrBeanConf) { // 自动配置缺少的 class, name 属性 $aBeanFactory->_typeProperties($arrBeanConf, 'view', is_int($key) ? null : $key, 'name'); // 默认 class if (empty($arrBeanConf['class'])) { $arrBeanConf['class'] = 'view'; } // 默认关闭 vagrant container if (!isset($arrBeanConf['vagrantContainer'])) { $arrBeanConf['vagrantContainer'] = false; } // 创建对象 $aBean = $aBeanFactory->createBean($arrBeanConf, $sNamespace, false); $aBean->setName($arrBeanConf['name']); $this->addFrameView($aBean); $aBean->buildBean($arrBeanConf, $sNamespace); if (!empty($arrBeanConf['model'])) { if (!($aModel = $aModelContainer->getByName($arrBeanConf['model']))) { throw new BeanConfException("视图(%s)的Bean配置属性 model 无效,没有指定的模型:%s", array($aBean->name(), $arrBeanConf['model'])); } $aBean->setModel($aModel); } } } // parent::buildBean($arrConfig, $sNamespace); }
private function buildItemFromBean(array $arrItemBean, $id = null) { $arrItemBean['class'] = __NAMESPACE__ . '\\Item'; if (empty($arrItemBean['id']) && !is_int($id)) { $arrItemBean['id'] = $id; } $aItem = BeanFactory::singleton()->createBean($arrItemBean, '*', false); // 在BuildBean中,通过query设置active需要先获得知道view()对象 if (!$aItem->view()) { $aItem->setView($this->view()); } $aItem->buildBean($arrItemBean); // addItem时,为了避免重复,需要先知道id值,所以只能放在buildBean之后 $this->addItemPrivate($aItem); }
/** * @wiki /MVC模式/视图窗体(控件)/表单控件 * ==Bean配置数组== * {| * !属性 * !类型 * !默认值 * !可选 * !说明 * |-- -- * |value * |mixed * |无 * |可选 * |指定控件的值,用于指定值的参数可能是任何类型,如何体现这些值由控件对象自行处理.一般来说,如果是input标签控件,这个值会放到input标签的value属性中,如果是select标签,这个值会让select标签选定特定的选项,其他控件也是类似的功能 * |-- -- * |valueString * |string * |无 * |可选 * |用string值指定控件的值,如果是input标签控件,这个值会放到input标签的value属性中,如果是select标签,这个值会让select标签选定特定的选项,其他控件也是类似的功能 * |-- -- * |formName * |string * |无 * |可选 * |控件在表单中的name值,无特殊需求不必指定,默认使用控件的id作为name * |-- -- * |readOnly * |boolean * |false * |可选 * |控件的只读特性,实质上是在控件的html上指定readonly属性 * |-- -- * |disabled * |boolean * |false * |可选 * |控件是否禁用,实质上是在控件的html上指定disabled属性 * |-- -- * |verifiers * |array * |无 * |可选 * |控件附带的校验器列表,每个数组元素都是一个校验器的初始化数组 * |} */ public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { parent::buildBean($arrConfig, $sNamespace); if (array_key_exists('value', $arrConfig)) { $this->setValue($arrConfig['value']); } if (array_key_exists('valueString', $arrConfig)) { $this->setValueFromString($arrConfig['valueString']); } if (!empty($arrConfig['formName'])) { $this->setFormName($arrConfig['formName']); } if (array_key_exists('readOnly', $arrConfig)) { $this->setReadOnly($arrConfig['readOnly'] ? true : false); } if (array_key_exists('disabled', $arrConfig)) { $this->setDisabled($arrConfig['disabled'] ? true : false); } $aBeanFactory = BeanFactory::singleton(); // 将 verifier:xxxx 转换成 verifiers[] 结构 $aBeanFactory->_typeKeyStruct($arrConfig, array('verifier:' => 'verifiers')); // verifiers if (!empty($arrConfig['verifiers'])) { foreach ($arrConfig['verifiers'] as $key => &$arrVerifierConf) { // 自动配置缺少的 class 属性 $aBeanFactory->_typeProperties($arrVerifierConf, 'length', is_int($key) ? null : $key, 'class'); $this->addVerifier($aBeanFactory->createBean($arrVerifierConf, $sNamespace, true), isset($arrVerifierConf['message']) ? $arrVerifierConf['message'] : null, isset($arrVerifierConf['onfail']) ? $arrVerifierConf['onfail'] : null, isset($arrVerifierConf['onfail.argvs']) ? $arrVerifierConf['onfail.argvs'] : null); } } }
/** * @wiki /MVC模式/数据库模型/数据表关联 * ==Bean配置数组== * type string 指定关系类型 * fromkeys array 起始表列名 * tokeys array 目标表列名 * frombridgekeys array 起始桥接表列名 * tobridgekeys array 起始桥接表列名 * bridge string 桥接表名 * fromPrototype string 指定起源原型配置 * on string */ public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { if (!$this->aDB) { $this->aDB = DB::singleton(); } $arrConfigForToPrototype = $arrConfig; $arrConfigForToPrototype['class'] = 'prototype'; $this->aToPrototype = BeanFactory::singleton()->createBean($arrConfigForToPrototype, $sNamespace); $this->aToPrototype->setassociatedBy($this); if (!empty($arrConfig['type'])) { $this->nType = $arrConfig['type']; } if (!empty($arrConfig['fromkeys'])) { $this->setFromKeys($arrConfig['fromkeys']); } if (!empty($arrConfig['tokeys'])) { $this->setToKeys($arrConfig['tokeys']); } if (!empty($arrConfig['tobridgekeys'])) { $this->setToBridgeKeys($arrConfig['tobridgekeys']); } if (!empty($arrConfig['frombridgekeys'])) { $this->setFromBridgeKeys($arrConfig['frombridgekeys']); } if (!empty($arrConfig['bridge'])) { $this->sBridgeTable = $arrConfig['bridge']; } if (!empty($arrConfig['fromPrototype'])) { $this->aFromPrototype = $arrConfig['fromPrototype']; } if (!empty($arrConfig['on'])) { if (is_array($arrConfig['on'])) { $arrOnFactors = $arrConfig['on']; $this->arrOnRawSql['expr_type'] = 'clause_on'; $this->arrOnRawSql['subtree'] =& SQL::parseSql(array_shift($arrOnFactors), 'on', true); $aOnClause = new SQL($this->arrOnRawSql); $aOnClause->addFactors($arrOnFactors); } else { $this->arrOnRawSql['expr_type'] = 'clause_on'; $this->arrOnRawSql['subtree'] =& SQL::parseSql($arrConfig['on'], 'on', true); } } if (!empty($arrConfig['join'])) { $this->sJoinType = strtoupper($arrConfig['join']); } $this->done(); $this->arrBeanConfig = $arrConfig; }
/** * @wiki /认证和授权/授权-许可(Authorizer) * ==Bean配置数组== * {| * |perms * |可选 * |array * |perms属性数组的成员可以是字符串或数组: * |如果是字符串,则表示 IPermission 类的类名(可以是在 BeanFeactory 中注册过的别名),该类必须实现 ISingleton 接口; * 如果是数组,则表示一个 IPermission 对象的 Bean 配置数组。 * perms属性数组的键名如果是字符串类型,可以做为对应元素Bean Config的class属性。 * |} */ public function buildBean(array &$arrConfig, $sNamespace = '*', BeanFactory $aBeanFactory = null) { if (!$aBeanFactory) { $aBeanFactory = BeanFactory::singleton(); } if (!empty($arrConfig['perms'])) { if (!is_array($arrConfig['perms'])) { throw new BeanConfException('%s 类的Bean Config的属性 perms必须是数组格式,传入的格式是:%s', array(__CLASS__, Type::detectType($arrConfig['perms']))); } foreach ($arrConfig['perms'] as $key => &$config) { if (is_string($config)) { $sClass = $aBeanFactory->beanClassNameByAlias($config); if (!Type::hasImplements($sClass, 'org\\jecat\\framework\\pattern\\ISingletonable')) { throw new BeanConfException('Bean 类 %s(%s) 没有实现 org\\jecat\\framework\\pattern\\ISingletonable 接口,无法只是通过类名创建对象', array($config, $sClass)); } if (!Type::hasImplements($sClass, 'org\\jecat\\framework\\auth\\IPermission')) { throw new BeanConfException('Bean 类 %s(%s) 没有实现 org\\jecat\\framework\\auth\\IPermission 接口,不能做为许可对象', array($config, $sClass)); } $this->requirePermission($sClass::singleton()); } else { if (is_array($config)) { if (is_string($key) and empty($config['class'])) { $config['class'] = $key; } $aPermission = $aBeanFactory->createBean($config, $sNamespace, true); if (!$aPermission instanceof IPermission) { throw new BeanConfException('%s 的Bean配置中提供了无效的 Permission 配置:%s 不是一个实现 org\\jecat\\framework\\auth\\IPermission 接口的类', array(__CLASS__, $config['class'])); } $this->requirePermission($aPermission); } } } } $this->arrBeanConfig = $arrConfig; }
/** * @return org\jecat\framework\mvc\controller\Response */ public function response() { if (!$this->aResponse) { // 补充缺省的 frame 配置 if (empty($this->arrBeanConfig['rspn'])) { $this->aResponse = Response::singleton(); } else { if (!empty($this->arrBeanConfig['rspn']['class'])) { $this->arrBeanConfig['rspn']['class'] = 'org\\jecat\\framework\\mvc\\controller\\Response'; $this->aResponse = BeanFactory::singleton()->createBean($this->arrBeanConfig['rspn'], '*', false); } } } return $this->aResponse; }
private function buildSubMenu($subMenu) { if ($subMenu instanceof Menu) { $this->setSubMenu($subMenu); } else { if (is_string($subMenu)) { $this->setSubMenu(new Menu($subMenu)); } else { if (is_array($subMenu)) { $subMenu['class'] = __NAMESPACE__ . '\\Menu'; $aMenu = BeanFactory::singleton()->createBean($subMenu, '*', false); $this->setSubMenu($aMenu); $aMenu->buildBean($subMenu); } } } }
/** * @wiki /MVC模式/数据库模型/模型的基本操作(新建、保存、删除、加载) * ==模型的创建== * 模型的创建有两中方式,基于bean的创建以及基于原型(ProtoType)的直接创建,两中方式的创建原理其实都是基于原型的创建. * * * =Bean配置数组= * {| * !属性 * !类型 * !默认值 * !可选 * !说明 * |-- -- * |model-class * |string * |无 * |可选 * |用哪个类来实现模型对象 * |-- -- * |table * |string * |无 * |可选 * |对应的数据库表 * |-- -- * |name * |string * |无 * |可选 * |在原型关系中的名字,用来区分不同的原型 * |-- -- * |columns * |array * |无 * |可选 * |需要表中哪些列的数据 * |-- -- * |keys * |array * |无 * |可选 * |指定表中哪些列为主键,若指定了主键则使用这里的主键而忽略数据库主键,如果未指定则使用数据库指定的主键 * |-- -- * |alias * |string * |无 * |可选 * |别名 * |-- -- * |limit * |int * |无 * |可选 * |设置读取条目数目的上限,下限为0 * |-- -- * |limitLen * |int * |无 * |可选 * |设置读取条目数目的上限 * |-- -- * |limitFrom * |int * |无 * |可选 * |设置读取条目数目的下限 * |-- -- * |order * |array * |无 * |可选 * |指定依据某一列来排序,同时设置正序排列 * |-- -- * |orderAsc * |string * |无 * |可选 * |指定依据某一列正序排序 * |-- -- * |orderDesc * |string * |无 * |可选 * |指定依据某一列反序排序 * |-- -- * |orderRand * |bool * |无 * |可选 * |随机排列结果 * |-- -- * |where * |array * |无 * |可选 * |where条件(where的格式很有趣,是对Lisp风格的尝试) * |-- -- * |hasOne * |array * |无 * |可选 * |配置hasone关系 * |-- -- * |belongsTo * |array * |无 * |可选 * |配置belongsTo关系 * |-- -- * |hasMany * |array * |无 * |可选 * |配置hasMany关系 * |-- -- * |hasAndBelongsToMany * |array * |无 * |可选 * |配置hasAndBelongsToMany关系 * |} * [example title="/MVC模式/数据库模型/模型的基本操作(新建、保存、删除、加载)/新建(Bean)"] */ public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { if (!empty($arrConfig['model-class'])) { $this->sModelClass = $arrConfig['model-class']; } // table if (!empty($arrConfig['table'])) { $this->setTableName($arrConfig['table']); } else { if (!empty($arrConfig['name'])) { $this->setTableName($arrConfig['name']); } } if (!empty($arrConfig['forceIndex'])) { $this->sForceIndex = $arrConfig['forceIndex']; } // name if (!empty($arrConfig['name'])) { $this->setName($arrConfig['name']); } else { if (!empty($arrConfig['table'])) { $this->setName($arrConfig['table']); } } // columns if (key_exists('columns', $arrConfig)) { call_user_func(array($this, 'addColumns'), $arrConfig['columns']); } // keys if (!empty($arrConfig['keys'])) { $this->setKeys($arrConfig['keys']); } // alias if (!empty($arrConfig['alias'])) { $this->addColumnAlias($arrConfig['alias']); } // limit ---------------- if (!empty($arrConfig['limit'])) { $this->nLimitLen = $arrConfig['limit']; } // limitLen if (!empty($arrConfig['limitLen'])) { $this->nLimitLen = $arrConfig['limitLen']; } // limitFrom if (!empty($arrConfig['limitFrom'])) { $this->limitFrom = $arrConfig['limitFrom']; } if ($this->nLimitLen === -1) { $this->criteria()->clearLimit(); } else { $this->criteria()->setLimit($this->nLimitLen, $this->limitFrom); } // order ---------------- if (!empty($arrConfig['order'])) { foreach ((array) $arrConfig['order'] as $sColumn) { list($sTable, $sColumn) = SQL::splitColumn($sColumn); $this->criteria()->addOrderBy($sColumn, true, $sTable); } } // orderDesc if (!empty($arrConfig['orderDesc'])) { foreach ((array) $arrConfig['orderDesc'] as $sColumn) { list($sTable, $sColumn) = SQL::splitColumn($sColumn); $this->criteria()->addOrderBy($sColumn, true, $sTable); } } // orderAsc if (!empty($arrConfig['orderAsc'])) { foreach ((array) $arrConfig['orderAsc'] as $sColumn) { list($sTable, $sColumn) = SQL::splitColumn($sColumn); $this->criteria()->addOrderBy($sColumn, false, $sTable); } } // orderRand if (!empty($arrConfig['orderRand']) && ($arrConfig['orderRand'] = true)) { $this->criteria()->orders()->add(null, Order::rand); } // groupby if (!empty($arrConfig['groupby'])) { foreach ((array) $arrConfig['groupby'] as $sColumn) { $this->criteria()->addGroupBy($sColumn); } } // where if (!empty($arrConfig['where'])) { $arrRawWhere =& $this->criteria()->rawClause(SQL::CLAUSE_WHERE); if (is_array($arrConfig['where'])) { $arrOnFactors = $arrConfig['where']; $arrRawWhere['subtree'] =& SQL::parseSql(array_shift($arrOnFactors), 'where', true); if ($arrOnFactors) { $this->criteria()->where()->addFactors($arrOnFactors); } } else { $arrRawWhere['subtree'] =& SQL::parseSql($arrConfig['where'], 'where', true); } // self::buildBeanRestriction($arrConfig['where'],$this->criteria()->where()->createRestriction()) ; } // associations $aBeanFactory = BeanFactory::singleton(); foreach ($arrConfig as $sConfigKey => &$item) { if (strpos($sConfigKey, 'hasOne:') === 0) { $item['type'] = Association::hasOne; $item['name'] = substr($sConfigKey, 7); } else { if (strpos($sConfigKey, 'belongsTo:') === 0) { $item['type'] = Association::belongsTo; $item['name'] = substr($sConfigKey, 10); } else { if (strpos($sConfigKey, 'hasMany:') === 0) { $item['type'] = Association::hasMany; $item['name'] = substr($sConfigKey, 8); } else { if (strpos($sConfigKey, 'hasAndBelongsToMany:') === 0) { $item['type'] = Association::hasAndBelongsToMany; $item['name'] = substr($sConfigKey, 20); } else { continue; } } } } if (empty($item['class'])) { $item['class'] = 'association'; } $item['fromPrototype'] = $this; $aAssociation = $aBeanFactory->createBean($item, $sNamespace, $aBeanFactory); unset($item['fromPrototype']); $aAssociation->setDB($this->db()); $this->arrAssociations[] = $aAssociation; } $this->done(); $this->arrBeanConfig = $arrConfig; }
/** * @wiki /MVC模式/视图/视图的Bean配置数组 * ==Bean配置数组== * {| * !属性 * !类型 * !默认值 * !可选 * !说明 * |-- -- * |name * |string * |无 * |必须 * |Jecat框架区分视图的唯一参照 * |-- -- * |template * |string * |无 * |可选 * |对应模板文件名 * |-- -- * |views * |array * |无 * |可选 * |子视图,元素为一个视图的bean数组 * |-- -- * |widgets * |array * |无 * |可选 * |子控件,元素为一个控件的bean数组 * |-- -- * |vars * |array * |无 * |可选 * |用于初始化视图对象的参数,以参数名为键,参数值为值 * |-- -- * |css * |string * |无 * |可选 * |显示视图时,套上一层 div wrapper,用在 div wrapper 上的 css class 名称 * |} */ public function buildBean(array &$arrConfig, $sNamespace = '*', \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { $aBeanFactory = BeanFactory::singleton(); // 将 widget:xxxx 转换成 widgets[] 结构 $aBeanFactory->_typeKeyStruct($arrConfig, array('view:' => 'views', 'widget:' => 'widgets')); // views if (!empty($arrConfig['views'])) { foreach ($arrConfig['views'] as $key => &$arrBeanConf) { // 自动配置缺少的 class, name 属性 $aBeanFactory->_typeProperties($arrBeanConf, 'view', is_int($key) ? null : $key, 'name'); $this->add($aBeanFactory->createBean($arrBeanConf, $sNamespace, true)); } } // widgets if (!empty($arrConfig['widgets'])) { foreach ($arrConfig['widgets'] as $key => &$arrBeanConf) { // 自动配置缺少的 class, name 属性 $aBeanFactory->_typeProperties($arrBeanConf, 'text', is_int($key) ? null : $key, 'id'); // 创建对象 $aWidget = $aBeanFactory->createBean($arrBeanConf, $sNamespace, false); if (!empty($arrBeanConf['id'])) { $aWidget->setId($arrBeanConf['id']); } // 添加到视图 $this->addWidget($aWidget, empty($arrConfig['widgets'][$key]['exchange']) ? null : $arrConfig['widgets'][$key]['exchange']); // 完成初始化 $aWidget->buildBean($arrConfig['widgets'][$key], $sNamespace); } } // vars if (!empty($arrConfig['vars'])) { $aVariables = $this->variables(); foreach ($arrConfig['vars'] as $sName => &$variable) { $aVariables->set($sName, $variable); } } // if (!empty($arrConfig['cssClass'])) { $this->setCssClass($arrConfig['cssClass']); } $this->arrBeanConfig = $arrConfig; }
public static function createBean(array &$arrConfig, $sNamespace = '*', $bBuildAtOnce, \org\jecat\framework\bean\BeanFactory $aBeanFactory = null) { if (!empty($arrConfig['orm'])) { if (!empty($arrConfig['name'])) { $arrConfig['orm']['name'] = $arrConfig['name']; } if (empty($arrConfig['orm']['class'])) { $arrConfig['orm']['class'] = 'prototype'; } if (empty($arrConfig['orm']['model-class'])) { $arrConfig['orm']['model-class'] = $arrConfig['class']; } if (!($aPrototype = BeanFactory::singleton()->createBean($arrConfig['orm'], $sNamespace))) { throw new BeanConfException("无法创建orm bean: %s , %s", array($sNamespace, var_export($arrConfig['orm'], true))); } $aBean = $aPrototype->createModel(!empty($arrConfig['list'])); } else { $sClass = get_called_class(); $aBean = new $sClass(); } if ($bBuildAtOnce) { $aBean->buildBean($arrConfig, $sNamespace, $aBeanFactory); } return $aBean; }