/** * Создает и возвращает объект валидатора * * @param string $sName Имя валидатора или метода при использовании параметра $oObject * @param LsObject $oObject Объект в котором необходимо вызвать метод валидации * @param null|array $aFields Список полей сущности для которых необходимо провести валидацию * @param array $aParams Параметры * * @return ModuleValidate_EntityValidator */ public function CreateValidator($sName, $oObject, $aFields = null, $aParams = array()) { if (is_string($aFields)) { $aFields = preg_split('/[\\s,]+/', $aFields, -1, PREG_SPLIT_NO_EMPTY); } // * Определяем список сценариев валидации if (isset($aParams['on'])) { if (is_array($aParams['on'])) { $aOn = $aParams['on']; } else { $aOn = preg_split('/[\\s,]+/', $aParams['on'], -1, PREG_SPLIT_NO_EMPTY); } } else { $aOn = array(); } // * Если в качестве имени валидатора указан метод объекта, то создаем специальный валидатор $sMethod = 'validate' . F::StrCamelize($sName); if (method_exists($oObject, $sMethod)) { /** @var ModuleValidate_EntityValidator $oValidator */ $oValidator = E::GetEntity('ModuleValidate_EntityValidatorInline'); if (!is_null($aFields)) { $oValidator->fields = $aFields; } $oValidator->object = $oObject; $oValidator->method = $sMethod; $oValidator->params = $aParams; if (isset($aParams['skipOnError'])) { $oValidator->skipOnError = $aParams['skipOnError']; } } else { // * Иначе создаем валидатор по имени if (!is_null($aFields)) { $aParams['fields'] = $aFields; } $sValidateName = 'Validator' . F::StrCamelize($sName); /** @var ModuleValidate_EntityValidator $oValidator */ $oValidator = E::GetEntity('ModuleValidate_Entity' . $sValidateName); foreach ($aParams as $sNameParam => $sValue) { $oValidator->{$sNameParam} = $sValue; } } $oValidator->on = empty($aOn) ? array() : array_combine($aOn, $aOn); return $oValidator; }
/** * Загрузка плагинов и делегирование * */ protected function LoadPlugins() { if ($aPluginList = F::GetPluginsList()) { foreach ($aPluginList as $sPluginName) { $sClassName = 'Plugin' . F::StrCamelize($sPluginName); /** @var Plugin $oPlugin */ $oPlugin = new $sClassName(); $oPlugin->Delegate(); $this->aPlugins[$sPluginName] = $oPlugin; } } }
/** * Возвращает имя метода обработки режима заполнения меню * * @param string $sModeName Название режима заполнения * @return string */ private function _getProcessMethodName($sModeName) { return 'Process' . F::StrCamelize($sModeName) . 'Mode'; }
/** * Деактивация * * @param string $sPluginId - код плагина * * @return null|bool */ public function Deactivate($sPluginId) { // получаем список активированных плагинов $aPlugins = $this->GetPluginsList(true); if (!isset($aPlugins[$sPluginId])) { return null; } $sPluginName = F::StrCamelize($sPluginId); $sPluginDir = $aPlugins[$sPluginId]->getDirname(); if (!$sPluginDir) { $sPluginDir = $sPluginId; } $sClassName = "Plugin{$sPluginName}"; if (class_exists($sClassName)) { /** @var Plugin $oPlugin */ $oPlugin = new $sClassName(); /** * TODO: Проверять зависимые плагины перед деактивацией */ $bResult = $oPlugin->Deactivate(); } else { // Исполняемый файл плагина не найден $sFile = F::File_NormPath("{$this->sPluginsCommonDir}{$sPluginDir}/Plugin{$sPluginName}.class.php"); E::ModuleMessage()->AddError(E::ModuleLang()->Get('action.admin.plugin_file_not_found', array('file' => $sFile)), E::ModuleLang()->Get('error'), true); return false; } if ($bResult) { // * Переопределяем список активированных пользователем плагинов $aActivePlugins = $this->GetActivePlugins(); // * Вносим данные в файл о деактивации плагина unset($aActivePlugins[$sPluginId]); // * Сбрасываем весь кеш, т.к. могут быть закешированы унаследованые плагинами сущности E::ModuleCache()->SetDesabled(true); E::ModuleCache()->Clean(); if (!$this->SetActivePlugins($aActivePlugins)) { E::ModuleMessage()->AddError(E::ModuleLang()->Get('action.admin.plugin_activation_file_write_error'), E::ModuleLang()->Get('error'), true); return false; } // * Очищаем компилированные шаблоны Smarty E::ModuleViewer()->ClearSmartyFiles(); } return $bResult; }
/** * Make standard class name from plugin id * * @param string $sPluginId * * @return string */ public static function GetPluginClass($sPluginId) { if ($sPluginId) { return 'Plugin' . F::StrCamelize($sPluginId); } return null; }
/** * Проверяет массив правил. В качестве правил может быть задана колбэк-функция * или указан метод владельца сущности, который должен быть реализован заранее * * @param $aRules * @param bool $bConcatenateResult * @param bool $sOwnerClassName * @return bool */ public function checkCustomRules($aRules, $bConcatenateResult = FALSE, $sOwnerClassName = FALSE) { // Ключ кэша $sCacheKey = md5(serialize($aRules) . (string) $bConcatenateResult . (string) $sOwnerClassName); if (!(FALSE === ($data = E::ModuleCache()->GetTmp($sCacheKey)))) { return $data; } // Правило жёстко задано - вернем его if (is_bool($aRules)) { return $aRules; } // Правило жёстко задано - вернем его if (is_string($aRules)) { return $aRules; } /** @var callable[]|[][] $aActiveRule Правило вычисления активности */ // Нет правила, кнопка вообще не активна будет if (!$aRules) { return FALSE; } // Правило задается методаом меню if (!is_array($aRules)) { return FALSE; } if (!$sOwnerClassName) { $aOwnerClassName = E::getInstance()->GetClassInfo($this, Engine::CI_MODULE); $sOwnerClassName = reset($aOwnerClassName); } // Все проверки пройдены, запускаем вычисление активности $bResult = FALSE; foreach ($aRules as $sMethodName => $xRule) { if (is_bool($xRule)) { if ($bConcatenateResult) { $bResult .= $xRule; } else { $bResult = $bResult || $xRule; } if ($bResult && !$bConcatenateResult) { break; } continue; } if (is_string($xRule) && $bConcatenateResult) { if (strpos($xRule, 'hook:') === 0) { $bResult .= E::ModuleHook()->Run(substr($xRule, 5)); } elseif (strpos($xRule, 'text:') === 0) { $bResult .= substr($xRule, 5); } elseif (strpos($xRule, 'func:') === 0) { $bResult .= call_user_func(substr($xRule, 5)); } else { $bResult .= $xRule; } continue; } // Передан колбэк if (is_callable($xRule)) { $bResult = $bResult || $xRule(); if ($bResult && !$bConcatenateResult) { break; } continue; } /** * Передан вызов функции, например * $xRule = array('compare_action' => array('index')) */ $sTmpMethodName = FALSE; $aTmpMethodParams = FALSE; // Метод передан строкой if (is_int($sMethodName) && is_string($xRule)) { $sTmpMethodName = $xRule; $aTmpMethodParams = array(); } // Метод передан массивом if (is_string($sMethodName) && is_array($xRule)) { $sTmpMethodName = $sMethodName; $aTmpMethodParams = $xRule; } // Вызовем метод if ($sTmpMethodName && $aTmpMethodParams !== FALSE) { if (strpos($sTmpMethodName, 'hook:') === 0) { $xCallResult = E::ModuleHook()->Run(substr($sTmpMethodName, 5), $aTmpMethodParams, false); } elseif (strpos($sTmpMethodName, 'text:') === 0) { $xCallResult = substr($sTmpMethodName, 5); } elseif (strpos($sTmpMethodName, 'func:') === 0) { $xCallResult = call_user_func_array(substr($sTmpMethodName, 5), $aTmpMethodParams); } else { $sTmpMethodName = $sOwnerClassName . '_' . F::StrCamelize($sTmpMethodName); $xCallResult = call_user_func_array(array($this, $sTmpMethodName), $aTmpMethodParams); } if ($bConcatenateResult) { if (!empty($xCallResult) && (is_string($xCallResult) || is_numeric($xCallResult))) { $bResult .= $xCallResult; } } else { $bResult = $bResult || $xCallResult; } if ($bResult && !$bConcatenateResult) { break; } continue; } } // Закэшируем результат E::ModuleCache()->SetTmp($bResult, $sCacheKey); return $bResult; }
/** * Автоопределение класса или файла экшена * * @param string $sAction * @param string $sEvent * @param bool $bFullPath * * @return string|null */ public static function SeekActionClass($sAction, $sEvent = null, $bFullPath = false) { $bOk = false; $sActionClass = ''; $sFileName = 'Action' . ucfirst($sAction) . '.class.php'; // Сначала проверяем файл экшена среди стандартных $aSeekDirs = array(Config::Get('path.dir.app'), Config::Get('path.dir.common')); if ($sActionFile = F::File_Exists('/classes/actions/' . $sFileName, $aSeekDirs)) { $sActionClass = 'Action' . ucfirst($sAction); $bOk = true; } else { // Если нет, то проверяем файл экшена среди плагинов $aPlugins = F::GetPluginsList(false, false); foreach ($aPlugins as $sPlugin => $aPluginInfo) { if ($sActionFile = F::File_Exists('plugins/' . $aPluginInfo['dirname'] . '/classes/actions/' . $sFileName, $aSeekDirs)) { $sActionClass = 'Plugin' . F::StrCamelize($sPlugin) . '_Action' . ucfirst($sAction); $bOk = true; break; } } } if ($bOk) { return $bFullPath ? $sActionFile : $sActionClass; } return null; }
function func_camelize($sStr) { return F::StrCamelize($sStr); }
/** * Проверка объекта * * @param string $sTargetType Тип владельца * @param int $iTargetId ID владельца * * @return bool */ public function CheckTarget($sTargetType, $iTargetId) { if (!$this->IsAllowTargetType($sTargetType)) { return false; } $sMethod = 'CheckTarget' . F::StrCamelize($sTargetType); if (method_exists($this, $sMethod)) { return $this->{$sMethod}($iTargetId); } return false; }
/** * Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля. * Также обрабатывает различные ORM методы сущности, например * <pre> * $oUser->Save(); * $oUser->Delete(); * </pre> * И методы модуля ORM, например * <pre> * E::ModuleUser()->GetUserItemsByName('Claus'); * E::ModuleUser()->GetUserItemsAll(); * </pre> * * @see Engine::_CallModule * * @param string $sName Имя метода * @param array $aArgs Аргументы * * @return mixed */ public function __call($sName, $aArgs) { if (preg_match("@^add([\\w]+)\$@i", $sName, $aMatch)) { return $this->_AddEntity($aArgs[0]); } if (preg_match("@^update([\\w]+)\$@i", $sName, $aMatch)) { return $this->_UpdateEntity($aArgs[0]); } if (preg_match("@^save([\\w]+)\$@i", $sName, $aMatch)) { return $this->_SaveEntity($aArgs[0]); } 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]); } if (preg_match("@^showcolumnsfrom([\\w]+)\$@i", $sName, $aMatch)) { return $this->_ShowColumnsFrom($aArgs[0]); } if (preg_match("@^showprimaryindexfrom([\\w]+)\$@i", $sName, $aMatch)) { return $this->_ShowPrimaryIndexFrom($aArgs[0]); } if (preg_match("@^getchildrenof([\\w]+)\$@i", $sName, $aMatch)) { return $this->_GetChildrenOfEntity($aArgs[0]); } if (preg_match("@^getparentof([\\w]+)\$@i", $sName, $aMatch)) { return $this->_GetParentOfEntity($aArgs[0]); } if (preg_match("@^getdescendantsof([\\w]+)\$@i", $sName, $aMatch)) { return $this->_GetDescendantsOfEntity($aArgs[0]); } if (preg_match("@^getancestorsof([\\w]+)\$@i", $sName, $aMatch)) { return $this->_GetAncestorsOfEntity($aArgs[0]); } if (preg_match("@^loadtreeof([\\w]+)\$@i", $sName, $aMatch)) { $sEntityFull = array_key_exists(1, $aMatch) ? $aMatch[1] : null; return $this->LoadTree($aArgs[0], $sEntityFull); } $sNameUnderscore = F::StrUnderscore($sName); $iEntityPosEnd = 0; if (strpos($sNameUnderscore, '_items') >= 3) { $iEntityPosEnd = strpos($sNameUnderscore, '_items'); } else { if (strpos($sNameUnderscore, '_by') >= 3) { $iEntityPosEnd = strpos($sNameUnderscore, '_by'); } else { if (strpos($sNameUnderscore, '_all') >= 3) { $iEntityPosEnd = strpos($sNameUnderscore, '_all'); } } } if ($iEntityPosEnd && $iEntityPosEnd > 4) { $sEntityName = substr($sNameUnderscore, 4, $iEntityPosEnd - 4); } else { $sEntityName = F::StrUnderscore(E::GetModuleName($this)) . '_'; $sNameUnderscore = substr_replace($sNameUnderscore, $sEntityName, 4, 0); $iEntityPosEnd = strlen($sEntityName) - 1 + 4; } $sNameUnderscore = substr_replace($sNameUnderscore, str_replace('_', '', $sEntityName), 4, $iEntityPosEnd - 4); $sEntityName = F::StrCamelize($sEntityName); /** * getUserItemsByFilter() get_user_items_by_filter */ if (preg_match("@^get_([a-z]+)((_items)|())_by_filter\$@i", $sNameUnderscore, $aMatch)) { if ($aMatch[2] == '_items') { return $this->GetItemsByFilter($aArgs[0], $sEntityName); } else { return $this->GetByFilter($aArgs[0], $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]), $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], F::StrCamelize($sEntityName)); } /** * getUserByLogin() get_user_by_login * getUserByLoginAndMail() get_user_by_login_and_mail * getUserItemsByName() get_user_items_by_name * getUserItemsByNameAndActive() get_user_items_by_name_and_active * getUserItemsByDateRegisterGte() get_user_items_by_date_register_gte (>=) * getUserItemsByProfileNameLike() get_user_items_by_profile_name_like * getUserItemsByCityIdIn() get_user_items_by_city_id_in */ if (preg_match("@^get_([a-z]+)((_items)|())_by_([_a-z]+)\$@i", $sNameUnderscore, $aMatch)) { $aAliases = array('_gte' => ' >=', '_lte' => ' <=', '_gt' => ' >', '_lt' => ' <', '_like' => ' LIKE', '_in' => ' IN'); $sSearchParams = str_replace(array_keys($aAliases), array_values($aAliases), $aMatch[5]); $aSearchParams = explode('_and_', $sSearchParams); $aSplit = array_chunk($aArgs, count($aSearchParams)); $aFilter = array_combine($aSearchParams, $aSplit[0]); if (isset($aSplit[1][0])) { $aFilter = array_merge($aFilter, $aSplit[1][0]); } if ($aMatch[2] == '_items') { return $this->GetItemsByFilter($aFilter, $sEntityName); } else { return $this->GetByFilter($aFilter, $sEntityName); } } /** * getUserAll() get_user_all OR * getUserItemsAll() get_user_items_all */ if (preg_match("@^get_([a-z]+)_all\$@i", $sNameUnderscore, $aMatch) || preg_match("@^get_([a-z]+)_items_all\$@i", $sNameUnderscore, $aMatch)) { $aFilter = array(); if (isset($aArgs[0]) && is_array($aArgs[0])) { $aFilter = $aArgs[0]; } return $this->GetItemsByFilter($aFilter, $sEntityName); } return $this->oEngine->_CallModule($sName, $aArgs); }
/** * Возвращает URL страницы с объектом подписки * Актуально при переходе по ссылки с отпиской от рассылки и последующим редиректом * * @param string $sTargetType Тип * @param int $iTargetId ID владельца * * @return bool */ public function GetUrlTarget($sTargetType, $iTargetId) { $sMethod = 'GetUrlTarget' . F::StrCamelize($sTargetType); if (method_exists($this, $sMethod)) { return $this->{$sMethod}($iTargetId); } return false; }
/** * @param string $sName * @param string|null $sPlugin * @param bool $bReturnClassName * * @return string|bool */ protected function _fileClassExists($sName, $sPlugin = null, $bReturnClassName = false) { if (!$sPlugin) { $aPathSeek = Config::Get('path.root.seek'); $sFile = '/classes/widgets/Widget' . $sName . '.class.php'; $sClass = 'Widget' . $sName; } else { $aPathSeek = array(Plugin::GetPath($sPlugin)); $sFile = '/classes/widgets/Widget' . $sName . '.class.php'; $sClass = 'Plugin' . F::StrCamelize($sPlugin) . '_Widget' . $sName; } if (F::File_Exists($sFile, $aPathSeek)) { return $bReturnClassName ? $sClass : $sFile; } return false; }
/** * Устанавливает значение поля текущей сущности * * @param string $sField * @param string|mixed $sValue */ protected function setValueOfCurrentEntity($sField, $sValue) { if ($this->oEntityCurrent) { //call_user_func_array(array($this->oEntityCurrent, 'set' . F::StrCamelize($sField)), array($sValue)); $sMethod = 'set' . F::StrCamelize($sField); $this->oEntityCurrent->{$sMethod}($sValue); } }
/** * Используется для доступа к связанным данным типа MANY_TO_MANY * * @param string $sName Название свойства к которому обращаемсяя * * @return mixed */ public function __get($sName) { // Обработка обращений к обёрткам связей MANY_TO_MANY // Если связь загружена, возвращаем объект связи if (isset($this->_aManyToManyRelations[F::StrUnderscore($sName)])) { return $this->_aManyToManyRelations[F::StrUnderscore($sName)]; // Есл не загружена, но связь с таким именем существет, пробуем загрузить и вернуть объект связи } elseif (isset($this->aRelations[F::StrUnderscore($sName)]) && $this->aRelations[F::StrUnderscore($sName)][0] == self::RELATION_TYPE_MANY_TO_MANY) { $sMethod = 'get' . F::StrCamelize($sName); $this->__call($sMethod, array()); if (isset($this->_aManyToManyRelations[F::StrUnderscore($sName)])) { return $this->_aManyToManyRelations[F::StrUnderscore($sName)]; } // В противном случае возвращаем то, что просили у объекта } else { return $this->{$sName}; } }