/** * Получить число сущностей по связанной таблице * * @param array $aJoinData Фильтр * @param string $sEntityFull Название класса сущности * * @return int */ public function GetCountItemsByJoinTable($aJoinData = array(), $sEntityFull = null) { if (is_null($sEntityFull)) { $sEntityFull = E::GetPluginPrefix($this) . 'Module' . E::GetModuleName($this) . '_Entity' . E::GetModuleName(get_class($this)); } elseif (!substr_count($sEntityFull, '_')) { $sEntityFull = E::GetPluginPrefix($this) . 'Module' . E::GetModuleName($this) . '_Entity' . $sEntityFull; } // Если параметр #cache указан и пуст, значит игнорируем кэширование для запроса if (array_key_exists('#cache', $aJoinData) && !$aJoinData['#cache']) { $iCount = $this->oMapper->GetCountItemsByJoinTable($aJoinData, $sEntityFull); } else { $sEntityFullRoot = E::ModulePlugin()->GetRootDelegater('entity', $sEntityFull); $sCacheKey = $sEntityFullRoot . '_count_items_by_join_table_' . serialize($aJoinData); $aCacheTags = array(); $iCacheTime = 60 * 60 * 24; // скорее лучше хранить в свойстве сущности, для возможности выборочного переопределения // переопределяем из параметров if (isset($aJoinData['#cache'][0])) { $sCacheKey = $aJoinData['#cache'][0]; } if (isset($aJoinData['#cache'][1])) { $aCacheTags = $aJoinData['#cache'][1]; } if (isset($aJoinData['#cache'][2])) { $iCacheTime = $aJoinData['#cache'][2]; } $aCacheTags[] = 'm2m_' . $aJoinData['#relation_key'] . $aJoinData['#by_key'] . $aJoinData['#by_value']; if (false === ($iCount = E::ModuleCache()->Get($sCacheKey))) { $iCount = $this->oMapper->GetCountItemsByJoinTable($aJoinData, $sEntityFull); E::ModuleCache()->Set($iCount, $sCacheKey, $aCacheTags, $iCacheTime); } } return $iCount; }
/** * Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля * Также производит обработку методов set* и get* * Учитывает связи и может возвращать связанные данные * * @see Engine::_CallModule * * @param string $sName Имя метода * @param array $aArgs Аргументы * * @return mixed */ public function __call($sName, $aArgs) { $sType = substr($sName, 0, strpos(F::StrUnderscore($sName), '_')); if (!strpos($sName, '_') && in_array($sType, array('get', 'set', 'reload'))) { $sKey = F::StrUnderscore(preg_replace('/' . $sType . '/', '', $sName, 1)); if ($sType == 'get') { if (isset($this->_aData[$sKey])) { return $this->_aData[$sKey]; } else { $sField = $this->_getField($sKey); if ($sField != $sKey && isset($this->_aData[$sField])) { return $this->_aData[$sField]; } } /** * Проверяем на связи */ if (array_key_exists($sKey, $this->aRelations)) { $sEntityRel = $this->aRelations[$sKey][1]; $sRelationType = $this->aRelations[$sKey][0]; $sRelationKey = $this->aRelations[$sKey][2]; $sRelationJoinTable = null; $sRelationJoinTableKey = 0; // foreign key в join-таблице для текущей сущности if ($sRelationType == self::RELATION_TYPE_MANY_TO_MANY && array_key_exists(3, $this->aRelations[$sKey])) { $sRelationJoinTable = $this->aRelations[$sKey][3]; $sRelationJoinTableKey = isset($this->aRelations[$sKey][4]) ? $this->aRelations[$sKey][4] : $this->_getPrimaryKey(); } /** * Если связь уже загруженна, то возвращаем сразу результат */ if (array_key_exists($sKey, $this->aRelationsData)) { return $this->aRelationsData[$sKey]; } $sRelModuleName = E::GetModuleName($sEntityRel); $sRelEntityName = E::GetEntityName($sEntityRel); $sRelPluginPrefix = E::GetPluginPrefix($sEntityRel); $sRelPrimaryKey = 'id'; if ($oRelEntity = E::GetEntity($sEntityRel)) { $sRelPrimaryKey = $oRelEntity->_getPrimaryKey(); } $iPrimaryKeyValue = $this->getProp($this->_getPrimaryKey()); $sCmd = ''; $mCmdArgs = array(); switch ($sRelationType) { case self::RELATION_TYPE_BELONGS_TO: $sCmd = "{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}By" . F::StrCamelize($sRelPrimaryKey); $mCmdArgs = $this->getProp($sRelationKey); break; case self::RELATION_TYPE_HAS_ONE: $sCmd = "{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}By" . F::StrCamelize($sRelationKey); $mCmdArgs = $iPrimaryKeyValue; break; case self::RELATION_TYPE_HAS_MANY: $sCmd = "{$sRelPluginPrefix}{$sRelModuleName}_get{$sRelEntityName}ItemsByFilter"; $mCmdArgs = array($sRelationKey => $iPrimaryKeyValue); break; case self::RELATION_TYPE_MANY_TO_MANY: $sCmd = "{$sRelPluginPrefix}Module{$sRelModuleName}_get{$sRelEntityName}ItemsByJoinTable"; $mCmdArgs = array('#join_table' => Config::Get($sRelationJoinTable), '#relation_key' => $sRelationKey, '#by_key' => $sRelationJoinTableKey, '#by_value' => $iPrimaryKeyValue, '#index-from-primary' => true); break; default: break; } // Нужно ли учитывать дополнительный фильтр $bUseFilter = is_array($mCmdArgs) && array_key_exists(0, $aArgs) && is_array($aArgs[0]); if ($bUseFilter) { $mCmdArgs = array_merge($mCmdArgs, $aArgs[0]); } $aCallArgs = array($mCmdArgs); $res = E::GetInstance()->_CallModule($sCmd, $aCallArgs); // Сохраняем данные только в случае "чистой" выборки if (!$bUseFilter) { $this->aRelationsData[$sKey] = $res; } // Создаём объекты-обёртки для связей MANY_TO_MANY if ($sRelationType == self::RELATION_TYPE_MANY_TO_MANY) { $this->_aManyToManyRelations[$sKey] = new LS_ManyToManyRelation($res); } return $res; } return null; } elseif ($sType == 'set' && array_key_exists(0, $aArgs)) { if (array_key_exists($sKey, $this->aRelations)) { $this->aRelationsData[$sKey] = $aArgs[0]; } else { $this->_aData[$this->_getField($sKey)] = $aArgs[0]; } } elseif ($sType == 'reload') { if (array_key_exists($sKey, $this->aRelationsData)) { unset($this->aRelationsData[$sKey]); return $this->__call('get' . F::StrCamelize($sKey), $aArgs); } } } else { return E::getInstance()->_CallModule($sName, $aArgs); } }