From 1054f9c8de6db688a8752379b757d380e88391f2 Mon Sep 17 00:00:00 2001 From: Mzhelskiy Maxim Date: Sun, 29 Aug 2010 07:03:53 +0000 Subject: [PATCH] update ORM by ajaxy --- engine/classes/EntityORM.class.php | 74 +++++++++++++++++++++++------- engine/classes/MapperORM.class.php | 37 +++++++++++---- engine/classes/ModuleORM.class.php | 63 +++++++++++++++++++++---- 3 files changed, 139 insertions(+), 35 deletions(-) diff --git a/engine/classes/EntityORM.class.php b/engine/classes/EntityORM.class.php index 28bcb709..3cd9f1af 100644 --- a/engine/classes/EntityORM.class.php +++ b/engine/classes/EntityORM.class.php @@ -24,6 +24,7 @@ abstract class EntityORM extends Entity { const RELATION_TYPE_BELONGS_TO='belongs_to'; const RELATION_TYPE_HAS_MANY='has_many'; const RELATION_TYPE_HAS_ONE='has_one'; + const RELATION_TYPE_MANY_TO_MANY='many_to_many'; protected $aRelations=array(); protected $aRelationsData=array(); @@ -36,7 +37,16 @@ abstract class EntityORM extends Entity { parent::__construct($aParam); } - public function _GetPrimatyKey() { + public function _GetPrimaryKey() { + if(!$this->_getDataOne($this->sPrimaryKey)) { + $sModulePrefix=null; + if (preg_match('/Entity([^_]+)/',get_class($this),$sModulePrefix)) { + $sModulePrefix=func_underscore($sModulePrefix[1]).'_'; + if($this->_getDataOne($sModulePrefix.$this->sPrimaryKey)) { + $this->sPrimaryKey=$sModulePrefix.$this->sPrimaryKey; + } + } + } return $this->sPrimaryKey; } @@ -62,6 +72,10 @@ abstract class EntityORM extends Entity { public function Delete() { return $this->_Method(__FUNCTION__); + } + + public function Reload() { + return $this->_Method(__FUNCTION__); } protected function _Method($sName) { @@ -89,9 +103,9 @@ abstract class EntityORM extends Entity { } public function __call($sName,$aArgs) { - $sType=strtolower(substr($sName,0,3)); - if (!strpos($sName,'_') and in_array($sType,array('get','set'))) { - $sKey=func_underscore(substr($sName,3)); + $sType=substr($sName,0,strpos(func_underscore($sName),'_')); + if (!strpos($sName,'_') and in_array($sType,array('get','set','reload'))) { + $sKey=func_underscore(str_replace($sType,'',$sName)); if ($sType=='get') { if (isset($this->_aData[$sKey])) { return $this->_aData[$sKey]; @@ -110,6 +124,10 @@ abstract class EntityORM extends Entity { $sEntityRel=$this->aRelations[$sKey][1]; $sRelationType=$this->aRelations[$sKey][0]; $sRelationKey=$this->aRelations[$sKey][2]; + $sRelationJoinTable=null; + if($sRelationType == self::RELATION_TYPE_MANY_TO_MANY && array_key_exists(3, $this->aRelations[$sKey])) { + $sRelationJoinTable=$this->aRelations[$sKey][3]; + } /** * Если связь уже загруженна, то возвращаем сразу результат @@ -118,28 +136,47 @@ abstract class EntityORM extends Entity { return $this->aRelationsData[$sKey]; } - $sModuleName=Engine::GetModuleName($sEntityRel); - $sEntityName=Engine::GetEntityName($sEntityRel); - $sPluginPrefix=Engine::GetPluginPrefix($sEntityRel); - $iPrimaryKeyValue=$this->_getDataOne($this->_GetPrimatyKey()); + $sRelModuleName=Engine::GetModuleName($sEntityRel); + $sRelEntityName=Engine::GetEntityName($sEntityRel); + $sRelPluginPrefix=Engine::GetPluginPrefix($sEntityRel); + $sRelPrimaryKey='id'; + if($oRelEntity=Engine::GetEntity($sEntityRel)) { + $sRelPrimaryKey=$oRelEntity->_GetPrimaryKey(); + } + + $iPrimaryKeyValue=$this->_getDataOne($this->_GetPrimaryKey()); $sCmd=''; $aCmdArgs=array(); switch ($sRelationType) { - case self::RELATION_TYPE_HAS_MANY : - $sCmd="{$sPluginPrefix}{$sModuleName}_get{$sEntityName}ItemsBy".func_camelize($sRelationKey); + case self::RELATION_TYPE_BELONGS_TO : + $sCmd="{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}By".func_camelize($sRelPrimaryKey); + $aCmdArgs[0]=$this->_getDataOne($sRelationKey); + break; + case self::RELATION_TYPE_HAS_ONE : + $sCmd="{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}By".func_camelize($sRelationKey); $aCmdArgs[0]=$iPrimaryKeyValue; break; - case self::RELATION_TYPE_BELONGS_TO : - $sCmd="{$sPluginPrefix}{$sModuleName}_get{$sEntityName}By".func_camelize($this->_GetPrimatyKey()); - $aCmdArgs[0]=$this->_getDataOne($sRelationKey); - case self::RELATION_TYPE_HAS_ONE : + case self::RELATION_TYPE_HAS_MANY : + $sCmd="{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}ItemsBy".func_camelize($sRelationKey); + $aCmdArgs[0]=$iPrimaryKeyValue; + break; + case self::RELATION_TYPE_MANY_TO_MANY : + $sCmd="{$sRelPluginPrefix}Module{$sRelModuleName}_get{$sRelEntityName}ItemsByJoinTable"; + $sByKey = strpos($this->_GetPrimaryKey(), $sModulePrefix) === 0 ? $this->_GetPrimaryKey() : $sModulePrefix.$this->_GetPrimaryKey(); + $aCmdArgs[0] = array( + 'join_table' => $sRelationJoinTable, + 'relation_key' => $sRelationKey, + 'by_key' => $sByKey, + 'by_value' => $iPrimaryKeyValue, + ); + break; default: break; - } + } $res=Engine::GetInstance()->_CallModule($sCmd,$aCmdArgs); - + $this->aRelationsData[$sKey]=$res; return $res; } @@ -151,6 +188,11 @@ abstract class EntityORM extends Entity { } else { $this->_aData[$sKey]=$aArgs[0]; } + } elseif ($sType=='reload') { + if (array_key_exists($sKey,$this->aRelationsData)) { + unset($this->aRelationsData[$sKey]); + return $this->__call('get'.func_camelize($sKey),$aArgs); + } } } else { return Engine::getInstance()->_CallModule($sName,$aArgs); diff --git a/engine/classes/MapperORM.class.php b/engine/classes/MapperORM.class.php index 12009e61..7c5d019c 100644 --- a/engine/classes/MapperORM.class.php +++ b/engine/classes/MapperORM.class.php @@ -28,20 +28,20 @@ class MapperORM extends Mapper { return $this->oDb->query($sql,$oEntity->_getData()); } - public function UpdateEntity($oEntity) { + public function UpdateEntity($oEntity) { $sTableName = self::GetTableName($oEntity); - $iPrimaryKeyValue=$oEntity->_getDataOne($oEntity->_GetPrimatyKey()); + $iPrimaryKeyValue=$oEntity->_getDataOne($oEntity->_GetPrimaryKey()); - $sql = "UPDATE ".$sTableName." SET ?a WHERE ".$oEntity->_GetPrimatyKey()." = ? "; + $sql = "UPDATE ".$sTableName." SET ?a WHERE ".$oEntity->_GetPrimaryKey()." = ? "; return $this->oDb->query($sql,$oEntity->_getData(),$iPrimaryKeyValue); } public function DeleteEntity($oEntity) { $sTableName = self::GetTableName($oEntity); - $iPrimaryKeyValue=$oEntity->_getDataOne($oEntity->_GetPrimatyKey()); + $iPrimaryKeyValue=$oEntity->_getDataOne($oEntity->_GetPrimaryKey()); - $sql = "DELETE FROM ".$sTableName." WHERE ".$oEntity->_GetPrimatyKey()." = ? "; + $sql = "DELETE FROM ".$sTableName." WHERE ".$oEntity->_GetPrimaryKey()." = ? "; return $this->oDb->query($sql,$iPrimaryKeyValue); } @@ -129,18 +129,35 @@ class MapperORM extends Mapper { return $aItems; } + public function GetItemsByJoinTable($aData,$sEntityFull) { + if(empty($aData)) { + return null; + } + $sTableName = self::GetTableName($sEntityFull); + $sql = "SELECT a.*, b.* FROM ?# a LEFT JOIN ".$sTableName." b USING(?#) WHERE a.?#=?"; + $aItems = array(); + if($aRows=$this->oDb->select($sql, $aData['join_table'], $aData['relation_key'], $aData['by_key'], $aData['by_value'])) { + foreach($aRows as $aRow) { + $oEntity=Engine::GetEntity($sEntityFull,$aRow); + $oEntity->_SetIsNew(false); + $aItems[] = $oEntity; + } + } + return $aItems; + } + public static function GetTableName($oEntity) { /** * Варианты таблиц: * prefix_user -> если модуль совпадает с сущностью * prefix_user_invite -> если модуль не сопадает с сущностью */ - $sModuleName = strtolower(Engine::GetModuleName($oEntity)); - $sEntityName = strtolower(Engine::GetEntityName($oEntity)); - if ($sModuleName==$sEntityName) { - $sTable=$sModuleName; + $sModuleName = func_underscore(Engine::GetModuleName($oEntity)); + $sEntityName = func_underscore(Engine::GetEntityName($oEntity)); + if (strpos($sEntityName,$sModuleName)===0) { + $sTable=func_underscore($sEntityName); } else { - $sTable=$sModuleName.'_'.$sEntityName; + $sTable=func_underscore($sModuleName).'_'.func_underscore($sEntityName); } if(Config::Get('db.table.'.$sTable)) { return Config::Get('db.table.'.$sTable); diff --git a/engine/classes/ModuleORM.class.php b/engine/classes/ModuleORM.class.php index 0cf81c58..daaa0f84 100644 --- a/engine/classes/ModuleORM.class.php +++ b/engine/classes/ModuleORM.class.php @@ -40,7 +40,7 @@ abstract class ModuleORM extends Module { return $oEntity; } elseif ($res) { // есть автоинкремент, устанавливаем его - $oEntity->_setData(array($oEntity->_GetPrimatyKey() => $res)); + $oEntity->_setData(array($oEntity->_GetPrimaryKey() => $res)); return $oEntity; } return false; @@ -73,6 +73,19 @@ abstract class ModuleORM extends Module { } else { return $this->_UpdateEntity($oEntity); } + } + + + protected function _ReloadEntity($oEntity) { + if($sPrimaryKey=$oEntity->_getPrimaryKey()) { + if($sPrimaryKeyValue=$oEntity->_getDataOne($sPrimaryKey)) { + if($oEntityNew=$this->GetByFilter(array($sPrimaryKey=>$sPrimaryKeyValue),Engine::GetEntityName($oEntity))) { + $oEntity->_setData($oEntityNew->_getData()); + return $oEntity; + } + } + } + return false; } @@ -129,7 +142,7 @@ abstract class ModuleORM extends Module { $sRelModuleName=Engine::GetModuleName($oRelEntityEmpty); $sRelEntityName=Engine::GetEntityName($oRelEntityEmpty); $sRelPluginPrefix=Engine::GetPluginPrefix($oRelEntityEmpty); - // ItemsByArrayId - id пока идет костылем, т.к. у стандартных сущностей нет метода _GetPrimatyKey() + // ItemsByArrayId - id пока идет костылем, т.к. у стандартных сущностей нет метода _GetPrimaryKey() $aRelData=Engine::GetInstance()->_CallModule("{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}ItemsByArrayId",array($aEntityKeys[$sRelKey])); /** * Собираем набор @@ -157,12 +170,21 @@ abstract class ModuleORM extends Module { $aData=$this->oMapperORM->GetItemsByArray($aFilter,$sEntityFull); foreach ($aData as $oEntity) { // здесь под вопросом какое поле использовать в качестве ключа, всегда примари или тот, который передан? - $aEntities[$oEntity->_getDataOne($oEntity->_GetPrimatyKey())]=$oEntity; + $aEntities[$oEntity->_getDataOne($oEntity->_GetPrimaryKey())]=$oEntity; } return $aEntities; } - public function __call($sName,$aArgs) { + public function GetItemsByJoinTable($aJoinData=array(),$sEntityFull=null) { + if (is_null($sEntityFull)) { + $sEntityFull=Engine::GetPluginPrefix($this).'Module'.Engine::GetModuleName($this).'_Entity'.Engine::GetModuleName(get_class($this)); + } elseif (!substr_count($sEntityFull,'_')) { + $sEntityFull=Engine::GetPluginPrefix($this).'Module'.Engine::GetModuleName($this).'_Entity'.$sEntityFull; + } + return $this->oMapperORM->GetItemsByJoinTable($aJoinData,$sEntityFull); + } + + public function __call($sName,$aArgs) { if (preg_match("@^add([\w]+)$@i",$sName,$aMatch)) { return $this->_AddEntity($aArgs[0]); } @@ -177,15 +199,38 @@ abstract class ModuleORM extends Module { if (preg_match("@^delete([\w]+)$@i",$sName,$aMatch)) { return $this->_DeleteEntity($aArgs[0]); + } + + if (preg_match("@^reload([\w]+)$@i",$sName,$aMatch)) { + return $this->_ReloadEntity($aArgs[0]); } $sNameUnderscore=func_underscore($sName); - + $iEntityPosEnd=strlen($sNameUnderscore)-1; + if(substr_count($sNameUnderscore,'_items')) { + $iEntityPosEnd=strpos($sNameUnderscore,'_items'); + } else if(substr_count($sNameUnderscore,'_by')) { + $iEntityPosEnd=strpos($sNameUnderscore,'_by'); + } else if(substr_count($sNameUnderscore,'_all')) { + $iEntityPosEnd=strpos($sNameUnderscore,'_all'); + } + $sEntityName=substr($sNameUnderscore,4,$iEntityPosEnd-4); + /** + * getUserRoleJoinByUserIdAndRoleId() get_user-role-join_by_user_id_and_role_id + */ + $sNameUnderscore=substr_replace($sNameUnderscore,str_replace('_','',$sEntityName),4,$iEntityPosEnd-4); + $sEntityName=func_camelize($sEntityName); /** * getUserItemsByArrayId() get_user_items_by_array_id */ if (preg_match("@^get_([a-z]+)_items_by_array_([_a-z]+)$@i",$sNameUnderscore,$aMatch)) { - return $this->GetItemsByArray(array($aMatch[2]=>$aArgs[0]),$aMatch[1]); + return $this->GetItemsByArray(array($aMatch[2]=>$aArgs[0]),$sEntityName); + } + /** + * getUserItemsByJoinTable() get_user_items_by_join_table + */ + if (preg_match("@^get_([a-z]+)_items_by_join_table$@i",$sNameUnderscore,$aMatch)) { + return $this->GetItemsByJoinTable($aArgs[0],func_camelize($sEntityName)); } /** * getUserByLogin() get_user_by_login @@ -197,9 +242,9 @@ abstract class ModuleORM extends Module { if (preg_match("@^get_([a-z]+)((_items)|())_by_([_a-z]+)$@i",$sNameUnderscore,$aMatch)) { $aFilter=array_combine(explode('_and_',$aMatch[5]),$aArgs); if ($aMatch[2]=='_items') { - return $this->GetItemsByFilter($aFilter,$aMatch[1]); + return $this->GetItemsByFilter($aFilter,$sEntityName); } else { - return $this->GetByFilter($aFilter,$aMatch[1]); + return $this->GetByFilter($aFilter,$sEntityName); } } /** @@ -210,7 +255,7 @@ abstract class ModuleORM extends Module { if (isset($aArgs[0]) and is_array($aArgs[0])) { $aFilter=$aArgs[0]; } - return $this->GetItemsByFilter($aFilter,$aMatch[1]); + return $this->GetItemsByFilter($aFilter,$sEntityName); } return $this->oEngine->_CallModule($sName,$aArgs);