Наследование одного екшена разными плагинами
Здесь я высказался о проблеме. Сегодня я расскажу как её решить, а точнее какие изменения внести в ядро 042 из последней транковой версии.
Проблема эта однажды коснется почти каждого т.к. она весьма серьезная и с ней столкнутся — раз плюнуть, поэтому пост заносим в избранное.
Коротко напомню суть проблемы — если два разных плагина наследуют один общий екшен (например ActionSettings), и оба плагина выводят что-то в шаблон, то один из плагинов (который был активирован первым) завершится ошибкой не нахождения шаблона.
Решение для LiveStreet версии 0.4.2. Перед тем как вносить изменения делайте резервные копии!
Решение затрагивает всего 3 файла в папке engine:
2 файла — папка classes — ActionPlugin.class.php и Action.class.php
1 из modules/plugin — Plugin.class.php.
UPD:
Все изменения я внес в стандартные файлы ядра ЛС 042 и сохранил в одном архиве с сохранением структуры папок, так что можно файлы просто скопировать поверх от корня сайта.
Итак, на первое:
Из engine/classes/ActionPlugin.class.php полностью удаляем функции
и
Второе блюдо:
В engine/classes/Action.class.php
Функцию
заменяем на
и функцию
заменяем на
Третье:
В engine/modules/plugin/Plugin.class.php добавить в конце:
После выполненных действий шаблоны начали работать.
Надеюсь кому-то поможет.
UPD:
Проблема эта однажды коснется почти каждого т.к. она весьма серьезная и с ней столкнутся — раз плюнуть, поэтому пост заносим в избранное.
Коротко напомню суть проблемы — если два разных плагина наследуют один общий екшен (например ActionSettings), и оба плагина выводят что-то в шаблон, то один из плагинов (который был активирован первым) завершится ошибкой не нахождения шаблона.
Fatal error: Uncaught exception 'Exception' with message 'Can not find the template: actions/ActionSettings/abc.tpl' in лалала
Решение для LiveStreet версии 0.4.2. Перед тем как вносить изменения делайте резервные копии!
Решение затрагивает всего 3 файла в папке engine:
2 файла — папка classes — ActionPlugin.class.php и Action.class.php
1 из modules/plugin — Plugin.class.php.
UPD:
Все изменения я внес в стандартные файлы ядра ЛС 042 и сохранил в одном архиве с сохранением структуры папок, так что можно файлы просто скопировать поверх от корня сайта.
Все изменения данного поста в этом архиве.
Итак, на первое:
Из engine/classes/ActionPlugin.class.php полностью удаляем функции
protected function SetTemplateAction($sTemplate)
и
public function GetTemplate()
Второе блюдо:
В engine/classes/Action.class.php
Функцию
protected function SetTemplateAction($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;
}
и функцию
public function GetTemplate()
заменяем на
public function GetTemplate() {
if (is_null($this->sActionTemplate)) {
$this->SetTemplateAction($this->sCurrentEvent);
}
return $this->sActionTemplate;
}
Третье:
В engine/modules/plugin/Plugin.class.php добавить в конце:
public function GetInherits($sFrom) {
if (isset($this->aInherits[trim($sFrom)])) {
return $this->aInherits[trim($sFrom)]['items'];
}
return null;
}
public function GetDelegates($sType,$sFrom) {
if (isset($this->aDelegates[$sType][$sFrom]['delegate'])) {
return array($this->aDelegates[$sType][$sFrom]['delegate']);
} else if($aInherits=$this->GetInherits($sFrom)) {
return array_map(create_function('$aInherit','return $aInherit["inherit"];'),array_reverse($aInherits));
}
return null;
}
public function GetDelegationChain($sType,$sTo) {
$sRootDelegater = $this->GetRootDelegater($sType,$sTo);
return $this->collectAllDelegatesRecursive($sType,array($sRootDelegater));
}
public function GetRootDelegater($sType,$sTo) {
$sItem = $sTo;
$sItemDelegater = $this->GetDelegater($sType,$sTo);
while(empty($sRootDelegater)) {
if($sItem==$sItemDelegater) {
$sRootDelegater = $sItem;
}
$sItem = $sItemDelegater;
$sItemDelegater = $this->GetDelegater($sType,$sItemDelegater);
}
return $sRootDelegater;
}
public function collectAllDelegatesRecursive($sType,$aDelegates) {
foreach($aDelegates as $sClass) {
if($aNewDelegates=$this->GetDelegates($sType,$sClass)) {
$aDelegates = array_merge($this->collectAllDelegatesRecursive($sType,$aNewDelegates),$aDelegates);
}
}
return $aDelegates;
}
После выполненных действий шаблоны начали работать.
Надеюсь кому-то поможет.
UPD:
Все изменения данного поста в этом архиве.
12 комментариев
а почему именно этот код? и туда? расскажите словами человека который понимает, что кто делегирует, наследует? один мудрый человек сказал, расскажи другим — поймешь сам.понимаю что теперь все будет работать как нужно, но словами рассказать что же было почему не работало рассказать сможешь??
Почему мне надо копипастить это ещё в этом топике? Те, кто столкнутся с этой проблемой используют патч и забудут о ней.
ну простите, нужно хотя бы чуть понимать в программировании почему именно «туда». Я же не могу людям, которые работают в других сферах объяснять тонкости работы кода, которой им сложно понять. А рассказывать что мы «редактируем модуль Plugin.class.php потому что он отвечает за работу с плагинами, где собственно проблема — по мне это чересчур. Пост ориентирован на программистов, т.к. они будут заниматься этим, т.к. просто пользователь определить эта ли ошибка у него на хостинге или нет — не сможет.
вы пишете что нужно заменить вот это
на это
Вот меня и всех интересует, почему имено на это? с чего вы взяли что Ваш код правельным будет, то что работает это не говорит что «правильно», поясните что происходило в функции до Ваших изменений и после?, прокомментируйте каждую строчку кода?
ЗЫ. остальные пока спят))
Доброй ночи.