diff --git a/engine/classes/Action.class.php b/engine/classes/Action.class.php index a2454de2..6e4ff409 100644 --- a/engine/classes/Action.class.php +++ b/engine/classes/Action.class.php @@ -15,6 +15,7 @@ --------------------------------------------------------- */ +require_once("Event.class.php"); /** * Абстрактный класс экшена. * @@ -31,6 +32,12 @@ abstract class Action extends LsObject { * @var array */ protected $aRegisterEvent=array(); + /** + * Список евентов, которые нужно обрабатывать внешним обработчиком + * + * @var array + */ + protected $aRegisterEventExternal=array(); /** * Список параметров из URL *
/action/event/param0/param1/../paramN/
@@ -126,13 +133,25 @@ abstract class Action extends LsObject { */ $aNames=(array)func_get_arg($iCountArgs-1); $aEvent['method']=$aNames[0]; + /** + * Определяем наличие внешнего обработчика евента + */ + $aEvent['external']=null; + $aMethod=explode('::',$aEvent['method']); + if (count($aMethod)>1) { + $aEvent['method']=$aMethod[1]; + $aEvent['external']=$aMethod[0]; + } + if (isset($aNames[1])) { $aEvent['name']=$aNames[1]; } else { $aEvent['name']=$aEvent['method']; } - if (!method_exists($this,$aEvent['method'])) { - throw new Exception("Method of the event not found: ".$aEvent['method']); + if (!$aEvent['external']) { + if (!method_exists($this,$aEvent['method'])) { + throw new Exception("Method of the event not found: ".$aEvent['method']); + } } $aEvent['preg']=func_get_arg(0); $aEvent['params_preg']=array(); @@ -142,6 +161,16 @@ abstract class Action extends LsObject { $this->aRegisterEvent[]=$aEvent; } + /** + * Регистрируем внешние обработчики для евентов + * + * @param string $sEventName + * @param string|array $sExternalClass + */ + protected function RegisterEventExternal($sEventName,$sExternalClass) { + $this->aRegisterEventExternal[$sEventName]=$sExternalClass; + } + /** * Запускает евент на выполнение * Если текущий евент не определен то запускается тот которые определен по умолчанию(default event) @@ -166,8 +195,27 @@ abstract class Action extends LsObject { } } $this->sCurrentEventName=$aEvent['name']; + if ($aEvent['external']) { + if (!isset($this->aRegisterEventExternal[$aEvent['external']])) { + throw new Exception("External processing for event not found: ".$aEvent['external']); + } + } $this->Hook_Run("action_event_".strtolower($this->sCurrentAction)."_before",array('event'=>$this->sCurrentEvent,'params'=>$this->GetParams())); - $result=call_user_func_array(array($this,$aEvent['method']),array()); + /** + * Проверяем на наличие внешнего обработчика евента + */ + if ($aEvent['external']) { + $oEvent=new $this->aRegisterEventExternal[$aEvent['external']]; + $oEvent->SetActionObject($this); + $oEvent->Init(); + if (!$aEvent['method']) { + $result=$oEvent->Exec(); + } else { + $result=call_user_func_array(array($oEvent,$aEvent['method']),array()); + } + } else { + $result=call_user_func_array(array($this,$aEvent['method']),array()); + } $this->Hook_Run("action_event_".strtolower($this->sCurrentAction)."_after",array('event'=>$this->sCurrentEvent,'params'=>$this->GetParams())); return $result; } diff --git a/engine/classes/Engine.class.php b/engine/classes/Engine.class.php index 005441b2..cd71bf38 100644 --- a/engine/classes/Engine.class.php +++ b/engine/classes/Engine.class.php @@ -106,6 +106,12 @@ class Engine extends LsObject { */ const CI_BLOCK = 256; + /** + * Имя обработчика евента + * @var int + */ + const CI_EVENT = 512; + /** * Префикс плагина * @var int @@ -139,10 +145,10 @@ class Engine extends LsObject { /** * Объекты - * CI_ACTION | CI_MAPPER | CI_HOOK | CI_PLUGIN | CI_ACTION | CI_MODULE | CI_ENTITY | CI_BLOCK + * CI_ACTION | CI_MAPPER | CI_HOOK | CI_PLUGIN | CI_EVENT | CI_MODULE | CI_ENTITY | CI_BLOCK * @var int */ - const CI_OBJECT = 351 ; + const CI_OBJECT = 863 ; /** * Текущий экземпляр движка, используется для синглтона. @@ -930,6 +936,12 @@ class Engine extends LsObject { : null ; } + if($iFlag & self::CI_EVENT){ + $aResult[self::CI_EVENT] = preg_match('/_Event([^_]+)/',$sClassName,$aMatches) + ? $aMatches[1] + : null + ; + } if($iFlag & self::CI_METHOD){ $sModuleName = isset($aResult[self::CI_MODULE]) ? $aResult[self::CI_MODULE] @@ -1027,6 +1039,19 @@ class Engine extends LsObject { $sPath = str_replace('/classes/modules/','/engine/modules/',$sPath); } } + }elseif($aInfo[self::CI_EVENT]){ + // Евент + if($aInfo[self::CI_PLUGIN]){ + // Евент плагина + $sPath .= 'plugins/'.func_underscore($aInfo[self::CI_PLUGIN]) + .'/classes/actions/'.lcfirst($aInfo[self::CI_ACTION]).'/Event'.$aInfo[self::CI_EVENT].'.class.php' + ; + }else{ + // Евент ядра + $sPath .= 'classes/actions/'.lcfirst($aInfo[self::CI_ACTION]).'/Event' + .$aInfo[self::CI_EVENT].'.class.php' + ; + } }elseif($aInfo[self::CI_ACTION]){ // Экшн if($aInfo[self::CI_PLUGIN]){ diff --git a/engine/classes/Event.class.php b/engine/classes/Event.class.php new file mode 100644 index 00000000..9e29993a --- /dev/null +++ b/engine/classes/Event.class.php @@ -0,0 +1,106 @@ +aMethodProxyAction as $sMethod) { + $aMethods[]=strtolower($sMethod); + } + $this->aMethodProxyAction=$aMethods; + } + + /** + * Устанавливает объект экшена + * + * @param Action $oAction Объект текущего экшена + */ + public function SetActionObject($oAction) { + $this->oAction=$oAction; + } + + /** + * Запускается для обработки евента, если у него не указанно имя, например, "User::" + */ + public function Exec() { + + } + + /** + * Запускается всегда перед вызовом метода евента + */ + public function Init() { + + } + + public function __get($sName) { + if (property_exists($this->oAction,$sName)) { + return $this->oAction->$sName; + } + } + + public function __set($sName,$mValue) { + if (property_exists($this->oAction,$sName)) { + return $this->oAction->$sName=$mValue; + } + } + + public function __call($sName,$aArgs) { + /** + * Обработка вызова приватных методов экшена + */ + if (in_array(strtolower($sName),$this->aMethodProxyAction)) { + array_unshift($aArgs,$sName); + return call_user_func_array(array($this->oAction,'ActionCall'),$aArgs); + } + /** + * Обработка вызова публичных методов экшена + */ + if (method_exists($this->oAction,$sName)) { + return call_user_func_array(array($this->oAction,$sName),$aArgs); + } + return Engine::getInstance()->_CallModule($sName,$aArgs); + } +} \ No newline at end of file