Наследование одного екшена разными плагинами
6
Здесь я высказался о проблеме. Сегодня я расскажу как её решить, а точнее какие изменения внести в ядро 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:
Все изменения данного поста в этом архиве.
- +1
- 03 августа 2011, 04:16
- PSNet
Поделились бы ходом решения, мыслями, почему именно так делали, понимаю что это программист должен знать, но понять где и что исправить не под силу каждому, особено тому кто начинает не с ООП. вообщем чтобы код был читабельным нужно не только использовать правильную структуру но и не забывать про комментарии.
Для вас да, тупо вставить и заменить код любой может
а почему именно этот код? и туда? расскажите словами человека который понимает, что кто делегирует, наследует? один мудрый человек сказал, расскажи другим — поймешь сам.понимаю что теперь все будет работать как нужно, но словами рассказать что же было почему не работало рассказать сможешь??
а почему именно этот код? и туда? расскажите словами человека который понимает, что кто делегирует, наследует? один мудрый человек сказал, расскажи другим — поймешь сам.понимаю что теперь все будет работать как нужно, но словами рассказать что же было почему не работало рассказать сможешь??
я все детально описал в предыдущем топике, что плагин который наследует системный класс ещё с одним плагином и который был активирован по очереди вторым — работает, а первый плагин — нет, т.к. шаблоны первого плагина ищутся в папке второго. Данный фикс избавляет от этой проблемы и основан на транковой версии движка.
Почему мне надо копипастить это ещё в этом топике? Те, кто столкнутся с этой проблемой используют патч и забудут о ней.
Почему мне надо копипастить это ещё в этом топике? Те, кто столкнутся с этой проблемой используют патч и забудут о ней.
а почему именно этот код?вот читать нужно внимательно кстати, в топике сказано почему именно этот код.
и тудану простите, нужно хотя бы чуть понимать в программировании почему именно «туда». Я же не могу людям, которые работают в других сферах объяснять тонкости работы кода, которой им сложно понять. А рассказывать что мы «редактируем модуль Plugin.class.php потому что он отвечает за работу с плагинами, где собственно проблема — по мне это чересчур. Пост ориентирован на программистов, т.к. они будут заниматься этим, т.к. просто пользователь определить эта ли ошибка у него на хостинге или нет — не сможет.
Я вас отлично понял, а Вы меня нет, писать комменты к функциям это очень полезно.читать код не нужно быть программистом, достаточно быть кодером. Вот что я хотел так вот пример:
вы пишете что нужно заменить вот это
на это
Вот меня и всех интересует, почему имено на это? с чего вы взяли что Ваш код правельным будет, то что работает это не говорит что «правильно», поясните что происходило в функции до Ваших изменений и после?, прокомментируйте каждую строчку кода?
вы пишете что нужно заменить вот это
public function GetTemplate() {
if (is_null($this->sActionTemplate)) {
$sActionClass=$this->GetActionClass();
/**
* Если класс не является делегатом плагина, устанавлваем шаблон по умолчанию.
* В случае делегирования, проверяем сначала имеет ли указанный плагин замену для шаблона.
*/
if(!$this->Plugin_isDelegated('action',$sActionClass)) {
$this->sActionTemplate='actions/'.$sActionClass.'/'.$this->sCurrentEvent.'.tpl';
} else {
$sDelegater = $this->Plugin_GetDelegater('action',$sActionClass);
$sTemplatePath = Plugin::GetTemplatePath($this->Plugin_GetDelegateSign('action',$sDelegater));
$this->sActionTemplate = is_file($sFile=$sTemplatePath.'actions/'.$sDelegater.'/'.$this->sCurrentEvent.'.tpl')
? $sFile
: 'actions/'.$sDelegater.'/'.$this->sCurrentEvent.'.tpl';
}
}
return $this->sActionTemplate;
}на это
public function GetTemplate() {
if (is_null($this->sActionTemplate)) {
$this->SetTemplateAction($this->sCurrentEvent);
}
return $this->sActionTemplate;
}Вот меня и всех интересует, почему имено на это? с чего вы взяли что Ваш код правельным будет, то что работает это не говорит что «правильно», поясните что происходило в функции до Ваших изменений и после?, прокомментируйте каждую строчку кода?
Вот меня и всех интересует, почему имено на это? с чего вы взяли что Ваш код правельным будет, то что работает это не говорит что «правильно», поясните что происходило в функции до Ваших изменений и после?, прокомментируйте каждую строчку кода?я вам ещё раз намекаю — перечитайте пост — там 100% сказано почему этот код, я не стебусь.
Вот меня и всех интересуетВас — вижу, да. А вот «всех» — нет. Только вам не понятно. Может тогда стоит не говорить за «всех»?
Комментарии (12)
RSS свернуть / развернуть