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/Action.class.php
2012-10-04 12:37:40 +04:00

380 lines
12 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*-------------------------------------------------------
*
* 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
*
---------------------------------------------------------
*/
/**
* Абстрактный класс экшена.
*
* От этого класса наследуются все экшены в движке.
* Предоставляет базовые метода для работы с параметрами и шаблоном при запросе страницы в браузере.
*
* @package engine
* @since 1.0
*/
abstract class Action extends LsObject {
/**
* Список зарегистрированных евентов
*
* @var array
*/
protected $aRegisterEvent=array();
/**
* Список параметров из URL
* <pre>/action/event/param0/param1/../paramN/</pre>
*
* @var array
*/
protected $aParams=array();
/**
* Список совпадений по регулярному выражению для евента
*
* @var array
*/
protected $aParamsEventMatch=array('event'=>array(),'params'=>array());
/**
* Объект ядра
*
* @var Engine|null
*/
protected $oEngine=null;
/**
* Шаблон экшена
* @see SetTemplate
* @see SetTemplateAction
*
* @var string|null
*/
protected $sActionTemplate=null;
/**
* Дефолтный евент
* @see SetDefaultEvent
*
* @var string|null
*/
protected $sDefaultEvent=null;
/**
* Текущий евент
*
* @var string|null
*/
protected $sCurrentEvent=null;
/**
* Имя текущий евента
* Позволяет именовать экшены на основе регулярных выражений
*
* @var string|null
*/
protected $sCurrentEventName=null;
/**
* Текущий экшен
*
* @var null|string
*/
protected $sCurrentAction=null;
/**
* Конструктор
*
* @param Engine $oEngine Объект ядра
* @param string $sAction Название экшена
*/
public function __construct(Engine $oEngine, $sAction) {
$this->RegisterEvent();
$this->oEngine=$oEngine;
$this->sCurrentAction=$sAction;
$this->aParams=Router::GetParams();
}
/**
* Добавляет евент в экшен
* По сути является оберткой для AddEventPreg(), оставлен для простоты и совместимости с прошлыми версиями ядра
* @see AddEventPreg
*
* @param string $sEventName Название евента
* @param string $sEventFunction Какой метод ему соответствует
*/
protected function AddEvent($sEventName,$sEventFunction) {
$this->AddEventPreg("/^{$sEventName}$/i",$sEventFunction);
}
/**
* Добавляет евент в экшен, используя регулярное выражение для евента и параметров
*
*/
protected function AddEventPreg() {
$iCountArgs=func_num_args();
if ($iCountArgs<2) {
throw new Exception("Incorrect number of arguments when adding events");
}
$aEvent=array();
/**
* Последний параметр может быть массивом - содержать имя метода и имя евента(именованный евент)
* Если указан только метод, то имя будет равным названию метода
*/
$aNames=(array)func_get_arg($iCountArgs-1);
$aEvent['method']=$aNames[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']);
}
$aEvent['preg']=func_get_arg(0);
$aEvent['params_preg']=array();
for ($i=1;$i<$iCountArgs-1;$i++) {
$aEvent['params_preg'][]=func_get_arg($i);
}
$this->aRegisterEvent[]=$aEvent;
}
/**
* Запускает евент на выполнение
* Если текущий евент не определен то запускается тот которые определен по умолчанию(default event)
*
* @return mixed
*/
public function ExecEvent() {
$this->sCurrentEvent=Router::GetActionEvent();
if ($this->sCurrentEvent==null) {
$this->sCurrentEvent=$this->GetDefaultEvent();
Router::SetActionEvent($this->sCurrentEvent);
}
foreach ($this->aRegisterEvent as $aEvent) {
if (preg_match($aEvent['preg'],$this->sCurrentEvent,$aMatch)) {
$this->aParamsEventMatch['event']=$aMatch;
$this->aParamsEventMatch['params']=array();
foreach ($aEvent['params_preg'] as $iKey => $sParamPreg) {
if (preg_match($sParamPreg,$this->GetParam($iKey,''),$aMatch)) {
$this->aParamsEventMatch['params'][$iKey]=$aMatch;
} else {
continue 2;
}
}
$this->sCurrentEventName=$aEvent['name'];
$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());
$this->Hook_Run("action_event_".strtolower($this->sCurrentAction)."_after",array('event'=>$this->sCurrentEvent,'params'=>$this->GetParams()));
return $result;
}
}
return $this->EventNotFound();
}
/**
* Устанавливает евент по умолчанию
*
* @param string $sEvent Имя евента
*/
public function SetDefaultEvent($sEvent) {
$this->sDefaultEvent=$sEvent;
}
/**
* Получает евент по умолчанию
*
* @return string
*/
public function GetDefaultEvent() {
return $this->sDefaultEvent;
}
/**
* Возвращает элементы совпадения по регулярному выражению для евента
*
* @param int|null $iItem Номер совпадения
* @return string|null
*/
protected function GetEventMatch($iItem=null) {
if ($iItem) {
if (isset($this->aParamsEventMatch['event'][$iItem])) {
return $this->aParamsEventMatch['event'][$iItem];
} else {
return null;
}
} else {
return $this->aParamsEventMatch['event'];
}
}
/**
* Возвращает элементы совпадения по регулярному выражению для параметров евента
*
* @param int $iParamNum Номер параметра, начинается с нуля
* @param int|null $iItem Номер совпадения, начинается с нуля
* @return string|null
*/
protected function GetParamEventMatch($iParamNum,$iItem=null) {
if (!is_null($iItem)) {
if (isset($this->aParamsEventMatch['params'][$iParamNum][$iItem])) {
return $this->aParamsEventMatch['params'][$iParamNum][$iItem];
} else {
return null;
}
} else {
if (isset($this->aParamsEventMatch['event'][$iParamNum])) {
return $this->aParamsEventMatch['event'][$iParamNum];
} else {
return null;
}
}
}
/**
* Получает параметр из URL по его номеру, если его нет то null
*
* @param int $iOffset Номер параметра, начинается с нуля
* @return mixed
*/
public function GetParam($iOffset,$default=null) {
$iOffset=(int)$iOffset;
return isset($this->aParams[$iOffset]) ? $this->aParams[$iOffset] : $default;
}
/**
* Получает список параметров из УРЛ
*
* @return array
*/
public function GetParams() {
return $this->aParams;
}
/**
* Установить значение параметра(эмуляция параметра в URL).
* После установки занова считывает параметры из роутера - для корректной работы
*
* @param int $iOffset Номер параметра, но по идеи может быть не только числом
* @param string $value
*/
public function SetParam($iOffset,$value) {
Router::SetParam($iOffset,$value);
$this->aParams=Router::GetParams();
}
/**
* Устанавливает какой шаблон выводить
*
* @param string $sTemplate Путь до шаблона относительно общего каталога шаблонов
*/
protected function SetTemplate($sTemplate) {
$this->sActionTemplate=$sTemplate;
}
/**
* Устанавливает какой шаблон выводить
*
* @param string $sTemplate Путь до шаблона относительно каталога шаблонов экшена
*/
protected function SetTemplateAction($sTemplate) {
$aDelegates = $this->Plugin_GetDelegationChain('action',$this->GetActionClass());
$sActionTemplatePath = $sTemplate.'.tpl';
foreach($aDelegates as $sAction) {
if(preg_match('/^(Plugin([\w]+)_)?Action([\w]+)$/i',$sAction,$aMatches)) {
$sTemplatePath = $this->Plugin_GetDelegate('template','actions/Action'.ucfirst($aMatches[3]).'/'.$sTemplate.'.tpl');
if(empty($aMatches[1])) {
$sActionTemplatePath = $sTemplatePath;
} else {
$sTemplatePath = Plugin::GetTemplatePath($sAction).$sTemplatePath;
if(is_file($sTemplatePath)) {
$sActionTemplatePath = $sTemplatePath;
break;
}
}
}
}
$this->sActionTemplate = $sActionTemplatePath;
}
/**
* Получить шаблон
* Если шаблон не определен то возвращаем дефолтный шаблон евента: action/{Action}.{event}.tpl
*
* @return string
*/
public function GetTemplate() {
if (is_null($this->sActionTemplate)) {
$this->SetTemplateAction($this->sCurrentEvent);
}
return $this->sActionTemplate;
}
/**
* Получить каталог с шаблонами экшена(совпадает с именем класса)
* @see Router::GetActionClass
*
* @return string
*/
public function GetActionClass() {
return Router::GetActionClass();
}
/**
* Возвращает имя евента
*
* @return null|string
*/
public function GetCurrentEventName() {
return $this->sCurrentEventName;
}
/**
* Вызывается в том случаи если не найден евент который запросили через URL
* По дефолту происходит перекидывание на страницу ошибки, это можно переопределить в наследнике
* @see Router::Action
*
* @return string
*/
protected function EventNotFound() {
return Router::Action('error','404');
}
/**
* Выполняется при завершение экшена, после вызова основного евента
*
*/
public function EventShutdown() {
}
/**
* Ставим хук на вызов неизвестного метода и считаем что хотели вызвать метод какого либо модуля
* @see Engine::_CallModule
*
* @param string $sName Имя метода
* @param array $aArgs Аргументы
* @return mixed
*/
public function __call($sName,$aArgs) {
return $this->oEngine->_CallModule($sName,$aArgs);
}
/**
* Абстрактный метод инициализации экшена
*
*/
abstract public function Init();
/**
* Абстрактный метод регистрации евентов.
* В нём необходимо вызывать метод AddEvent($sEventName,$sEventFunction)
*
*/
abstract protected function RegisterEvent();
}
?>