public function __get($sName) { // LS compatibility if ($sName === 'oEngine') { $this->oEngine = E::getInstance(); } return $this->oEngine; }
public function __get($sName) { // LS compatibility if ($sName === 'oEngine') { $this->oEngine = E::getInstance(); return $this->oEngine; } $trace = debug_backtrace(); $sError = 'Undefined property via __get(): ' . $sName . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line']; F::SysWarning($sError); return null; }
/** * Конструктор * * @param Engine $oEngine Объект ядра * @param string $sAction Название экшена */ public function __construct($oEngine, $sAction = null) { if (func_num_args() == 1 && is_string($oEngine)) { // Передан только экшен $this->oEngine = E::getInstance(); $sAction = $oEngine; } else { // LS-compatible $this->oEngine = $oEngine; } $this->_prepareRequestData(); //Engine::getInstance(); $this->sCurrentAction = $sAction; $this->aParams = R::GetParams(); $this->RegisterEvent(); //Config::ResetLevel(Config::LEVEL_ACTION); // Get current config level $iConfigLevel = C::GetLevel(); // load action's config if exists if ($sFile = F::File_Exists('/config/actions/' . $sAction . '.php', Config::Get('path.root.seek'))) { // Дополняем текущий конфиг конфигом экшена if ($aConfig = F::File_IncludeFile($sFile, true, true)) { // Текущий уровень конфига может быть как меньше LEVEL_ACTION, // так и больше. Нужно обновить все уровни if ($iConfigLevel <= Config::LEVEL_ACTION) { $iMinLevel = $iConfigLevel; $iMaxLevel = Config::LEVEL_ACTION; } else { $iMinLevel = Config::LEVEL_ACTION; $iMaxLevel = $iConfigLevel; } for ($iLevel = $iMinLevel; $iLevel <= $iMaxLevel; $iLevel++) { if ($iLevel > $iConfigLevel) { Config::ResetLevel(Config::LEVEL_ACTION); } Config::Load($aConfig, false, null, $iLevel, $sFile); } } } elseif ($iConfigLevel < Config::LEVEL_ACTION) { Config::ResetLevel(Config::LEVEL_ACTION); } }
/** * Проверяет массив правил. В качестве правил может быть задана колбэк-функция * или указан метод владельца сущности, который должен быть реализован заранее * * @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; }
/** * Запускает весь процесс :) * */ public function Exec() { $this->ParseUrl(); $this->DefineActionClass(); // Для возможности ДО инициализации модулей определить какой action/event запрошен $this->oEngine = E::getInstance(); $this->oEngine->Init(); // Подгружаем предыдущий URL, если он был $sData = E::ModuleSession()->GetCookie(static::BACKWARD_COOKIE); if ($sData) { $aData = F::Unserialize($sData); if (is_array($aData)) { $this->aBackwardUrl = $aData; } } // И сохраняем текущий, если это не ajax-запрос if (!F::AjaxRequest()) { E::ModuleSession()->SetCookie(static::BACKWARD_COOKIE, F::Serialize($this->aCurrentUrl, true)); } $this->ExecAction(); $this->Shutdown(false); }
/** * Возвращает имя таблицы для сущности * * @param EntityORM $oEntity Объект сущности * * @return string */ public static function GetTableName($oEntity) { /** * Варианты таблиц: * prefix_user -> если модуль совпадает с сущностью * prefix_user_invite -> если модуль не сопадает с сущностью */ $sClass = E::getInstance()->Plugin_GetDelegater('entity', is_object($oEntity) ? get_class($oEntity) : $oEntity); $sModuleName = F::StrUnderscore(E::GetModuleName($sClass)); $sEntityName = F::StrUnderscore(E::GetEntityName($sClass)); if (strpos($sEntityName, $sModuleName) === 0) { $sTable = F::StrUnderscore($sEntityName); } else { $sTable = F::StrUnderscore($sModuleName) . '_' . F::StrUnderscore($sEntityName); } /** * Если название таблиц переопределено в конфиге, то возвращаем его */ if (Config::Get('db.table.' . $sTable)) { return Config::Get('db.table.' . $sTable); } else { return Config::Get('db.table.prefix') . $sTable; } }
/** * Конструктор * * @param Engine $oEngine Объект ядра * @param string $sAction Название экшена */ public function __construct($oEngine, $sAction = null) { if (func_num_args() == 1 && is_string($oEngine)) { // Передан только экшен $this->oEngine = E::getInstance(); $sAction = $oEngine; } else { // LS-compatible $this->oEngine = $oEngine; } //Engine::getInstance(); $this->sCurrentAction = $sAction; $this->aParams = R::GetParams(); $this->RegisterEvent(); // load action's config if exists Config::ResetLevel(Config::LEVEL_ACTION); if ($sFile = F::File_Exists('/config/actions/' . $sAction . '.php', Config::Get('path.root.seek'))) { // Дополняем текущий конфиг конфигом экшена Config::LoadFromFile($sFile, false, Config::LEVEL_ACTION); } }
/** * Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля * Также производит обработку методов 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); } }