1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-07-03 06:55:03 +03:00
ifhub.club/engine/classes/Engine.class.php

722 lines
20 KiB
PHP
Raw Normal View History

<?php
2008-09-21 09:36:57 +03:00
/*-------------------------------------------------------
*
* LiveStreet Engine Social Networking
* Copyright © 2008 Mzhelskiy Maxim
*
*--------------------------------------------------------
*
* Official site: www.livestreet.ru
* Contact e-mail: rus.engine@gmail.com
*
* GNU General Public License, version 2:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
---------------------------------------------------------
*/
2009-07-26 16:43:16 +03:00
set_include_path(get_include_path().PATH_SEPARATOR.dirname(__FILE__));
require_once(Config::Get('path.root.engine').'/lib/internal/ProfilerSimple/Profiler.class.php');
2009-07-26 16:43:16 +03:00
require_once("Object.class.php");
require_once("Plugin.class.php");
2009-07-26 16:43:16 +03:00
require_once("Block.class.php");
require_once("Hook.class.php");
require_once("Module.class.php");
require_once("Router.class.php");
require_once("Entity.class.php");
require_once("Mapper.class.php");
2008-09-21 09:36:57 +03:00
/**
* Основной класс движка, который позволяет напрямую обращаться к любому модулю
*
*/
class Engine extends Object {
static protected $oInstance=null;
protected $aModules=array();
protected $aPlugins=array();
2008-09-21 09:36:57 +03:00
protected $aConfigModule;
public $iTimeLoadModule=0;
protected $iTimeInit=null;
2008-09-21 09:36:57 +03:00
2008-09-21 09:36:57 +03:00
/**
* При создании объекта делаем инициализацию
*
*/
protected function __construct() {
$this->iTimeInit=microtime(true);
2009-07-26 16:43:16 +03:00
if (get_magic_quotes_gpc()) {
func_stripslashes($_REQUEST);
2010-02-13 15:30:16 +02:00
func_stripslashes($_GET);
func_stripslashes($_POST);
func_stripslashes($_COOKIE);
2009-07-26 16:43:16 +03:00
}
2008-09-21 09:36:57 +03:00
}
/**
* Ограничиваем объект только одним экземпляром
*
* @return Engine
*/
static public function getInstance() {
if (isset(self::$oInstance) and (self::$oInstance instanceof self)) {
return self::$oInstance;
} else {
self::$oInstance= new self();
return self::$oInstance;
}
}
/**
* Инициализация
*
*/
2009-07-26 16:43:16 +03:00
public function Init() {
/**
* Загружаем плагины
*/
$this->LoadPlugins();
/**
* Инициализируем хуки
*/
$this->InitHooks();
/**
* Загружаем модули автозагрузки
*/
2009-07-26 16:43:16 +03:00
$this->LoadModules();
/**
* Инициализируем загруженные модули
*/
2009-07-26 16:43:16 +03:00
$this->InitModules();
/**
* Инициализируем загруженные плагины
*/
$this->InitPlugins();
/**
* Запускаем хуки для события завершения инициализации Engine
*/
$this->Hook_Run('engine_init_complete');
2009-07-26 16:43:16 +03:00
}
/**
* Завершение работы модуля
*
*/
public function Shutdown() {
$this->ShutdownModules();
2008-09-21 09:36:57 +03:00
}
/**
* Производит инициализацию всех модулей
*
*/
2009-07-26 16:43:16 +03:00
protected function InitModules() {
2008-09-21 09:36:57 +03:00
foreach ($this->aModules as $oModule) {
2010-02-04 21:44:19 +02:00
if(!$oModule->isInit()) {
/**
* Замеряем время инициализации модуля
*/
$oProfiler=ProfilerSimple::getInstance();
$iTimeId=$oProfiler->Start('InitModule',get_class($oModule));
2010-08-13 18:40:21 +03:00
$this->InitModule($oModule);
2010-02-04 21:44:19 +02:00
$oProfiler->Stop($iTimeId);
2010-02-04 21:26:38 +02:00
}
2008-09-21 09:36:57 +03:00
}
}
2010-08-13 18:40:21 +03:00
/**
* Инициализирует модуль
*
* @param unknown_type $oModule
*/
protected function InitModule($oModule){
$sOrigClassName = $sClassName = get_class($oModule);
$bRunHooks = false;
if($this->isInitModule('ModuleHook')){
$bRunHooks = true;
while(preg_match('#^Plugin#i', $sClassName)){
$sParentClassName = get_parent_class($sClassName);
if($sParentClassName == 'Module'){
break;
}
$sClassName = $sParentClassName;
}
}
if($bRunHooks || $sClassName == 'ModuleHook'){
$sHookPrefix = 'module_';
2010-08-14 01:40:01 +03:00
if($sPluginName = self::GetPluginName($sClassName)) {
2010-08-13 18:40:21 +03:00
$sHookPrefix .= "plugin{$sPluginName}_";
}
2010-08-14 01:40:01 +03:00
$sHookPrefix .= self::GetModuleName($sClassName).'_init_';
2010-08-13 18:40:21 +03:00
}
if($bRunHooks){
$this->Hook_Run($sHookPrefix.'before');
}
$oModule->Init();
$oModule->SetInit();
if($bRunHooks || $sClassName == 'ModuleHook'){
$this->Hook_Run($sHookPrefix.'after');
}
}
/**
* Проверяет модуль на инициализацию
*
* @param unknown_type $sModuleClass
* @return unknown
*/
public function isInitModule($sModuleClass) {
if(!in_array($sModuleClass,array('ModulePlugin','ModuleHook'))) {
$sModuleClass=$this->Plugin_GetDelegate('module',$sModuleClass);
}
if(isset($this->aModules[$sModuleClass]) and $this->aModules[$sModuleClass]->isInit()){
return true;
}
return false;
}
2008-09-21 09:36:57 +03:00
/**
* Завершаем работу всех модулей
*
*/
2009-07-26 16:43:16 +03:00
protected function ShutdownModules() {
foreach ($this->aModules as $sKey => $oModule) {
/**
* Замеряем время shutdown`a модуля
*/
$oProfiler=ProfilerSimple::getInstance();
$iTimeId=$oProfiler->Start('ShutdownModule',get_class($oModule));
2008-09-21 09:36:57 +03:00
$oModule->Shutdown();
$oProfiler->Stop($iTimeId);
2008-09-21 09:36:57 +03:00
}
}
/**
* Выполняет загрузку модуля по его названию
*
2010-08-13 18:40:21 +03:00
* @param string $sModuleClass
* @param bool $bInit - инициализировать модуль или нет
* @return Module
2008-09-21 09:36:57 +03:00
*/
2010-08-13 18:40:21 +03:00
public function LoadModule($sModuleClass,$bInit=false) {
$tm1=microtime(true);
/**
* Создаем объект модуля
*/
2010-08-13 18:40:21 +03:00
$oModule=new $sModuleClass($this);
$this->aModules[$sModuleClass]=$oModule;
if ($bInit or $sModuleClass=='ModuleCache') {
$this->InitModule($oModule);
}
2008-09-21 09:36:57 +03:00
$tm2=microtime(true);
$this->iTimeLoadModule+=$tm2-$tm1;
2010-08-13 18:40:21 +03:00
dump("load $sModuleClass - \t\t".($tm2-$tm1)."");
2008-09-21 09:36:57 +03:00
return $oModule;
}
/**
* Загружает все используемые модули и передает им в конструктор ядро
*
*/
protected function LoadModules() {
$this->LoadConfig();
2008-09-21 09:36:57 +03:00
foreach ($this->aConfigModule['autoLoad'] as $sModuleName) {
$sModuleClass='Module'.$sModuleName;
if(!in_array($sModuleName,array('Plugin','Hook'))) $sModuleClass=$this->Plugin_GetDelegate('module',$sModuleClass);
if (!isset($this->aModules[$sModuleClass])) {
$this->LoadModule($sModuleClass);
2010-02-13 15:09:48 +02:00
}
2008-09-21 09:36:57 +03:00
}
}
/**
* Выполняет загрузку конфигов
*
*/
protected function LoadConfig() {
$this->aConfigModule = Config::Get('module');
}
2009-05-09 20:04:04 +03:00
/**
* Регистрирует хуки из /classes/hooks/
*
*/
2009-07-26 16:43:16 +03:00
protected function InitHooks() {
$sDirHooks=Config::Get('path.root.server').'/classes/hooks/';
$aFiles=glob($sDirHooks.'Hook*.class.php');
if($aFiles and count($aFiles)) {
foreach ($aFiles as $sFile) {
if (preg_match("/Hook([\w]+)\.class\.php$/i",basename($sFile),$aMatch)) {
require_once($sFile);
$sClassName='Hook'.$aMatch[1];
$oHook=new $sClassName;
$oHook->RegisterHook();
}
}
}
/**
* Подгружаем хуки активных плагинов
*/
$this->InitPluginHooks();
}
/**
* Инициализация хуков активированных плагинов
*
*/
protected function InitPluginHooks() {
if($aPluginList = @file(Config::Get('path.root.server').'/plugins/plugins.dat')) {
$aPluginList=array_map('trim',$aPluginList);
$aFiles=array();
$sDirHooks=Config::Get('path.root.server').'/plugins/';
foreach ($aPluginList as $sPluginName) {
$aFiles=glob($sDirHooks.$sPluginName.'/classes/hooks/Hook*.class.php');
if($aFiles and count($aFiles)) {
foreach ($aFiles as $sFile) {
if (preg_match("/Hook([\w]+)\.class\.php$/i",basename($sFile),$aMatch)) {
require_once($sFile);
2010-03-06 21:34:00 +02:00
$sPluginName = ucfirst($sPluginName);
$sClassName="Plugin{$sPluginName}_Hook{$aMatch[1]}";
$oHook=new $sClassName;
$oHook->RegisterHook();
}
}
2009-05-09 20:04:04 +03:00
}
}
}
}
/**
* Загрузка плагинов и делегирование
*
*/
protected function LoadPlugins() {
if($aPluginList = @file(Config::Get('path.root.server').'/plugins/plugins.dat')) {
$aPluginList=array_map('trim',$aPluginList);
foreach ($aPluginList as $sPluginName) {
$sDirPlugins=Config::Get('path.root.server').'/plugins/';
2010-02-13 15:09:48 +02:00
$sPluginNameClass='Plugin'.ucfirst($sPluginName);
$sFile="{$sDirPlugins}{$sPluginName}/{$sPluginNameClass}.class.php";
if(is_file($sFile)) {
2010-02-13 15:09:48 +02:00
require_once($sFile);
$sClassName="{$sPluginNameClass}";
$oPlugin=new $sClassName;
$oPlugin->Delegate();
$this->aPlugins[$sPluginName]=$oPlugin;
}
}
}
}
/**
* Инициализация активированных плагинов
*
*/
protected function InitPlugins() {
foreach ($this->aPlugins as $oPlugin) {
$oPlugin->Init();
}
}
/**
* Возвращает список активных плагинов
*
* @return unknown
*/
public function GetPlugins() {
return $this->aPlugins;
}
/**
* Проверяет файл на существование, если используется кеширование memcache то кеширует результат работы
*
* @param string $sFile
* @return mixed
*/
2009-07-26 16:43:16 +03:00
public function isFileExists($sFile,$iTime=3600) { return file_exists($sFile);
if (strpos($sFile,'/Cache.class.')!==false) {
return file_exists($sFile);
}
if (SYS_CACHE_USE and SYS_CACHE_TYPE==SYS_CACHE_TYPE_MEMORY) {
if (false === ($data = $this->Cache_Get("file_exists_{$sFile}"))) {
$data=file_exists($sFile);
$this->Cache_Set((int)$data, "file_exists_{$sFile}", array(), $iTime);
}
return $data;
} else {
return file_exists($sFile);
}
}
2008-09-21 09:36:57 +03:00
/**
* Вызывает метод нужного модуля
*
* @param string $sName
* @param array $aArgs
* @return unknown
*/
public function _CallModule($sName,$aArgs) {
2008-09-21 09:36:57 +03:00
$sArgs='';
$aStrArgs=array();
foreach ($aArgs as $sKey => $arg) {
$aStrArgs[]='$aArgs['.$sKey.']';
}
$sArgs=join(',',$aStrArgs);
list($oModule,$sModuleName,$sMethod)=$this->GetModule($sName);
2008-09-21 09:36:57 +03:00
if (!method_exists($oModule,$sMethod)) {
2010-08-13 18:40:21 +03:00
// comment for ORM testing
//throw new Exception("The module has no required method: ".$sModuleName.'->'.$sMethod.'()');
}
2009-07-26 16:43:16 +03:00
$oProfiler=ProfilerSimple::getInstance();
$iTimeId=$oProfiler->Start('callModule',$sModuleName.'->'.$sMethod.'()');
$sModuleName=strtolower($sModuleName);
$aResultHook=array();
if (!in_array($sModuleName,array('plugin','hook'))) {
2010-03-28 00:53:39 +02:00
$aResultHook=$this->_CallModule('Hook_Run',array('module_'.$sModuleName.'_'.strtolower($sMethod).'_before',&$aArgs));
}
if (array_key_exists('delegate_result',$aResultHook)) {
$result=$aResultHook['delegate_result'];
} else {
2010-03-30 23:28:29 +03:00
$aArgsRef=array();
foreach ($aArgs as $key=>$v) {
$aArgsRef[]=&$aArgs[$key];
}
$result=call_user_func_array(array($oModule,$sMethod),$aArgsRef);
}
if (!in_array($sModuleName,array('plugin','hook'))) {
2010-07-06 14:54:52 +03:00
$this->Hook_Run('module_'.$sModuleName.'_'.strtolower($sMethod).'_after',array('result'=>&$result,'params'=>$aArgs));
}
2009-07-26 16:43:16 +03:00
$oProfiler->Stop($iTimeId);
return $result;
2008-09-21 09:36:57 +03:00
}
/**
* Возвращает объект модуля, имя модуля и имя вызванного метода
*
* @param string $sName
* @return array
*/
public function GetModule($sName) {
/**
* Поддержка полного синтаксиса при вызове метода модуля
*/
if (preg_match("/^Plugin(\w+)\_Module(\w+)\_(\w+)$/i",$sName,$aMatch)) {
$sName="Plugin{$aMatch[1]}_{$aMatch[2]}_{$aMatch[3]}";
}
if (preg_match("/^Module(\w+)\_(\w+)$/i",$sName,$aMatch)) {
$sName="{$aMatch[1]}_{$aMatch[2]}";
}
$aName=explode("_",$sName);
if(count($aName)==2) {
$sModuleName=$aName[0];
2010-06-01 19:20:30 +03:00
$sModuleClass='Module'.$aName[0];
$sMethod=$aName[1];
} else {
$sModuleName=$aName[0].'_'.$aName[1];
2010-06-01 19:20:30 +03:00
$sModuleClass=$aName[0].'_Module'.$aName[1];
$sMethod=$aName[2];
}
/**
* Подхватыем делегат модуля (в случае наличия такового)
*/
2010-06-01 19:20:30 +03:00
if(!in_array($sModuleName,array('Plugin','Hook'))) $sModuleClass=$this->Plugin_GetDelegate('module',$sModuleClass);
2010-06-01 19:20:30 +03:00
if (isset($this->aModules[$sModuleClass])) {
$oModule=$this->aModules[$sModuleClass];
} else {
2010-06-01 19:20:30 +03:00
$oModule=$this->LoadModule($sModuleClass,true);
}
return array($oModule,$sModuleName,$sMethod);
}
2009-07-26 16:43:16 +03:00
public function getStats() {
return array('sql'=>$this->Database_GetStats(),'cache'=>$this->Cache_GetStats(),'engine'=>array('time_load_module'=>round($this->iTimeLoadModule,3)));
}
public function GetTimeInit() {
return $this->iTimeInit;
}
2008-09-21 09:36:57 +03:00
/**
* Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля
*
* @param string $sName
* @param array $aArgs
* @return unknown
*/
public function __call($sName,$aArgs) {
return $this->_CallModule($sName,$aArgs);
}
/**
* Блокируем копирование/клонирование объекта роутинга
*
*/
protected function __clone() {
}
/**
* Получает объект маппера
*
* @param string $sClassName
* @param string $sName
* @return mixed
*/
public static function GetMapper($sClassName,$sName=null,$oConnect=null) {
if (preg_match("/^(?:Plugin\w+_)?Module(\w+)$/i",$sClassName,$aMatch)) {
if (!$sName) {
$sName=$aMatch[1];
}
$sClass=$sClassName.'_Mapper'.$sName;
if (!$oConnect) {
$oConnect=Engine::getInstance()->Database_GetConnect();
}
$sClass=self::getInstance()->Plugin_GetDelegate('mapper',$sClass);
return new $sClass($oConnect);
}
return null;
}
/**
* Создает объект сущности, контролируя варианты кастомизации
*
* @param string $sName
* @param mixed $aParams
* @return mixed
*/
public static function GetEntity($sName,$aParams=array()) {
/**
* Сущности, имеющие такое же название как модуль,
* можно вызывать сокращенно. Например, вместо User_User -> User
*/
switch (substr_count($sName,'_')) {
case 0:
$sEntity = $sModule = $sName;
break;
case 1:
/**
* Поддержка полного синтаксиса при вызове сущности
*/
if (preg_match("/^Module(\w+)\_Entity(\w+)$/i",$sName,$aMatch)) {
$sName="{$aMatch[1]}_{$aMatch[2]}";
}
list($sModule,$sEntity) = explode('_',$sName,2);
/**
* Обслуживание короткой записи сущностей плагинов
* PluginTest_Test -> PluginTest_ModuleTest_EntityTest
*/
if(substr($sModule,0,6)=='Plugin' and strlen($sModule)>6) {
$sPlugin = substr($sModule,6);
$sModule = $sEntity;
}
break;
case 2:
/**
* Поддержка полного синтаксиса при вызове сущности плагина
*/
if (preg_match("/^Plugin(\w+)\_Module(\w+)\_Entity(\w+)$/i",$sName,$aMatch)) {
$sName="Plugin{$aMatch[1]}_{$aMatch[2]}_{$aMatch[3]}";
}
/**
* Entity плагина
*/
if(substr($sName,0,6)=='Plugin') {
list($sPlugin,$sModule,$sEntity)=explode('_',$sName);
$sPlugin = substr($sPlugin,6);
} else {
throw new Exception("Unknown entity '{$sName}' given.");
}
break;
default:
throw new Exception("Unknown entity '{$sName}' given.");
}
$sClass=isset($sPlugin)
? 'Plugin'.$sPlugin.'_Module'.$sModule.'_Entity'.$sEntity
: 'Module'.$sModule.'_Entity'.$sEntity;
/**
* Определяем наличие делегата сущности
* Делегирование указывается только в полной форме!
*/
$sClass=self::getInstance()->Plugin_GetDelegate('entity',$sClass);
$oEntity=new $sClass($aParams);
return $oEntity;
}
2010-08-11 14:36:33 +03:00
public static function GetPluginName($oModule) {
if (preg_match('/Plugin([^_]+)/',is_string($oModule) ? $oModule : get_class($oModule),$aMatches)) {
if(isset($aMatches[1])) {
return $aMatches[1];
}
}
return null;
}
public static function GetPluginPrefix($oModule) {
if($sPluginName = self::GetPluginName($oModule)) {
return 'Plugin'.$sPluginName.'_';
}
return '';
}
public static function GetModuleName($oModule) {
if (preg_match('/Module([^_]+)/',is_string($oModule) ? $oModule : get_class($oModule),$aMatches)) {
if(isset($aMatches[1])) {
return $aMatches[1];
}
}
return null;
}
public static function GetEntityName($oEntity) {
2010-08-13 18:40:21 +03:00
if (preg_match('/Entity([^_]+)/',is_string($oEntity) ? $oEntity : get_class($oEntity),$aMatches)) {
2010-08-11 14:36:33 +03:00
if(isset($aMatches[1])) {
return $aMatches[1];
}
}
return null;
}
2008-09-21 09:36:57 +03:00
}
/**
* Автозагрузка кслассов
*
* @param unknown_type $sClassName
*/
function __autoload($sClassName) {
/**
* Если класс подходит под шаблон класса сущности то загружаем его
2008-09-21 09:36:57 +03:00
*/
if (preg_match("/^Module(\w+)\_Entity(\w+)$/i",$sClassName,$aMatch)) {
2008-09-21 09:36:57 +03:00
$tm1=microtime(true);
$sFileClass=Config::get('path.root.server').'/classes/modules/'.strtolower($aMatch[1]).'/entity/'.$aMatch[2].'.entity.class.php';
2008-09-21 09:36:57 +03:00
if (file_exists($sFileClass)) {
require_once($sFileClass);
$tm2=microtime(true);
dump($sClassName." - \t\t".($tm2-$tm1));
}
}
/**
* Если класс подходит под шаблон класса сущности плагина
*/
if (preg_match("/^Plugin(\w+)\_Module(\w+)\_Entity(\w+)$/i",$sClassName,$aMatch)) {
$tm1=microtime(true);
$sFileClass= Config::get('path.root.server').'/plugins/'.strtolower($aMatch[1]).'/classes/modules/'.strtolower($aMatch[2]).'/entity/'.$aMatch[3].'.entity.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
$tm2=microtime(true);
dump($sClassName." - \t\t".($tm2-$tm1));
}
}
/**
* Если класс подходит под шаблон модуля, то загружаем его
*/
if(preg_match("/^Module(\w+)$/i",$sClassName,$aMatch)) {
2010-06-02 13:12:42 +03:00
$sName = ucfirst($aMatch[1]);
$sFileClass= Config::get('path.root.server').'/classes/modules/'.strtolower($sName).'/'.$sName.'.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
} else {
$sFileClass = str_replace('/classes/modules/','/engine/modules/',$sFileClass);
if(file_exists($sFileClass)) require_once($sFileClass);
}
}
/**
* Если класс подходит под шаблон класса маппера, то загружаем его
*/
if (preg_match("/^Module(\w+)\_Mapper(\w+)$/i",$sClassName,$aMatch)) {
$sFileClass=Config::get('path.root.server').'/classes/modules/'.strtolower($aMatch[1]).'/mapper/'.$aMatch[2].'.mapper.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
}
}
/**
* Если класс подходит под шаблон класса маппера плагина, то загружаем его
*/
if (preg_match("/^Plugin(\w+)\_Module(\w+)\_Mapper(\w+)$/i",$sClassName,$aMatch)) {
2010-06-01 19:20:30 +03:00
$sFileClass=Config::get('path.root.server').'/plugins/'.strtolower($aMatch[1]).'/classes/modules/'.strtolower($aMatch[2]).'/mapper/'.$aMatch[3].'.mapper.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
}
}
/**
* Если класс подходит под шаблон модуля плагина
*/
if (preg_match("/^Plugin(\w+)\_Module(\w+)$/i",$sClassName,$aMatch)) {
$sFileClass=Config::get('path.root.server').'/plugins/'.strtolower($aMatch[1]).'/classes/modules/'.strtolower($aMatch[2]).'/'.$aMatch[2].'.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
}
}
/**
* Загрузка цепочки наследуемых классов
*/
if (preg_match("/^Plugin(\w+)\_Inherit\_([\w\_]+)$/i",$sClassName,$aMatch)) {
$sPlugin=$aMatch[1];
$sInheritClass=$aMatch[2];
$sParentClass=Engine::getInstance()->Plugin_GetParentInherit($sInheritClass);
class_alias($sParentClass,$sClassName);
}
/**
* Загрузка класса экшена
*/
if (preg_match("/^Action(\w+)$/i",$sClassName,$aMatch)) {
$sFileClass=Config::get('path.root.server').'/classes/actions/'.$sClassName.'.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
}
}
/**
* Загрузка класса экшена плагина
*/
if (preg_match("/^Plugin(\w+)\_Action(\w+)$/i",$sClassName,$aMatch)) {
$sFileClass=Config::get('path.root.server').'/plugins/'.strtolower($aMatch[1]).'/classes/actions/Action'.$aMatch[2].'.class.php';
if (file_exists($sFileClass)) {
require_once($sFileClass);
}
}
2008-09-21 09:36:57 +03:00
}
?>