Руководство по созданию плагина для v.0.4 на примере "Лента друзей"
82Предисловие
Что такое плагины — .
По мотивам , выполняю обещание — привожу руководство как сделать в виде плагина. Всех тонкостей в одной заметке не расскажешь, но основное постараюсь изложить.
Примечание. Долго не публиковал этот материал, держал в черновиках — на случай «мало-ли-что-измениться». Но думаю, кардинальных изменений в механизме плагинов в ближайшем релизе уже не будет.
Пошаговая схема:
1. Создаем директорию и основные файлы плагинаНазовем плагин Friends Feed, но для краткости в названиях файлов и директорий будем использовать просто friends. Поэтому создаем директорию friends в директории plugins.
Вкладываем туда файлы PluginFriends.class.php и plugin.xml
PluginFriend.class.php
<?php
/**
* Плагин предназначен для выведения пользователю списка топиков его друзей
*
* by Alex Kachayev <kachayev@gmail.com>
*/
class PluginFriends extends Plugin {
/**
* Активация плагина
* В принципе, здесь нам делать ничего не нужно
*/
public function Activate() {
return true;
}
/**
* Инициализация плагина
*/
public function Init() {
$this->Viewer_AddMenu('blog',Plugin::GetTemplatePath(__CLASS__).'/menu.blog.tpl');
}
/**
* Деактивация плагина
* В принципе, тут тоже ничего не нужно делать
*/
public function Deactivate() {
return true;
}
}
Примечание. Функции Activate(), Deactivate() можно было и не создавать, добавил просто чтоб напомнить о возможности их использования. В функции Init() «всплывает» достаточно интересный момент — замена стандартного меню, но об этом мы поговорим чуть позже.
Plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<plugin>
<name>
<lang name="default">Friends Feed</lang>
<lang name="russian">Лента Друзей</lang>
</name>
<author>
<lang name="default">Alex Kachayev</lang>
<lang name="russian">Алексей Качаев</lang>
</author>
<homepage>http://kachayev.ru/</homepage>
<version>0.8.1</version>
<requires>
<livestreet>0.4.0</livestreet>
<plugins>
</plugins>
</requires>
<description>
<lang name="default">Show topics that are wrote by your friends.</lang>
<lang name="russian">Вывод записей друзей отдельной лентой.</lang>
</description>
<delegate>
<module></module>
<action></action>
<template></template>
<entity></entity>
</delegate>
</plugin>Если все правильно сделали, то с этого момента плагин существует и формально функционирует. Т.е. зайдя в панель управления плагинами (/admin/plugins) вы уже можете увидеть новый «пункт» и произвести активацию\деактивацию. Правда нам это пока ничего не даст, ибо функционала еще не предусмотрено =)
2. Роутинг и конфигурация
Учтем, что лента друзей должна быть доступна по определенному URL. Например, /friends. Значит нам нужно добавить новое правило роутинга. Сделать это нужно в файле конфигурации плагина. Создаем директорию /friends/config/ и вкладываем туда файл config.php — эта конфигурация будет автоматически загружена, если плагин активирован администратором проекта.
Пока от нас требуется только указать новый «пункт» роутинга. Сделаем это вызовом Config::Set(). Для демонстрации работы конфигурации плагина, я также добавлю параметр работы плагина — количество выводимых записей на страницу (в учебных целях, в рабочем проекте я бы воспользовался значением этого параметра для остальных экшенов).
config.php:
/**
* Плагин предназначен для выведения пользователю списка топиков его друзей
*
* by Alex Kachayev <kachayev@gmail.com>
*/
$config['per_page'] = 10; // Число топиков на одну страницу ленты
Config::Set('router.page.friends', 'PluginFriends_ActionFeed');
return $config;
3. Action для вывода записей и модуль
Для начала сделаем модуль для получения записей, написанных друзьями. В папке /plugins/friends/ создаем директорию /classes/modules/friends и вкладываем туда файл Friends.class.php:
<?php
class PluginFriends_Friends extends Module {
public function Init() {
}
/**
* Получает число новых топиков в ленте друзей
*
* @return array
*/
public function GetCountTopicsFriendsNew($sUserId) {
$sDate=date("Y-m-d H:00:00",time()-Config::Get('module.topic.new_time'));
$aFriends = $this->User_GetUsersFriend($sUserId);
if(!is_array($aFriends) or count($aFriends)==0) {
return 0;
}
$aFilter=array(
'user_id' => array_keys($aFriends),
'topic_publish' => 1,
'topic_new' => $sDate,
);
$s=serialize($aFilter);
if (false === ($data = $this->Cache_Get("topic_friend_count_{$s}"))) {
$data = $this->Topic_GetCountTopicsByFilter($aFilter);
$this->Cache_Set($data, "topic_friend_count_{$s}", array('topic_update','topic_new'), 60*5);
}
return $data;
}
/**
* Получает все топики в ленте друзей
*
* @return array
*/
public function GetTopicsFriends($sUserId,$iPage,$iPerPage) {
/**
* Получаем идентификаторы друзей пользователя
*/
$aFriends = $this->User_GetUsersFriend($sUserId);
if(!is_array($aFriends) or count($aFriends)==0) {
return array('count'=>0, 'collection'=>array());
}
$aFilter=array(
'user_id' => array_keys($aFriends),
'topic_publish' => 1,
'blog_type' => array('open','personal')
);
return $this->Topic_GetTopicsByFilter($aFilter,$iPage,$iPerPage);
}
public function Shutdown() {
}
}
?>
Как видите, в этом файле, мы создаем новый модуль PluginFriends_Friends, предназначенный для: а) получения списка топиков в ленте друзей, б) получения количество топиков в ленте друзей. По сути ничего необычно, единственное отличие от простого модуля — приставка в названии с указанием на плагин Friends.
Создаем экшен для обработки вывода записей Ленты Друзей. Для этого в директории /friends/classes/ создаем директорию actions и вкладываем туда файл ActionFeed.class.php:
<?php
class PluginFriends_ActionFeed extends ActionPlugin {
/**
* Главное меню
*
* @var unknown_type
*/
protected $sMenuHeadItemSelect='blog';
/**
* Меню
*
* @var unknown_type
*/
protected $sMenuItemSelect='index';
/**
* Субменю
*
* @var unknown_type
*/
protected $sMenuSubItemSelect='friends';
/**
* Число новых топиков
*
* @var unknown_type
*/
protected $iCountTopicsNew=0;
/**
* Число новых топиков в ленте друзей
*
* @var unknown_type
*/
protected $iCountTopicsFriendsNew=0;
/**
* Число новых топиков в коллективных блогах
*
* @var unknown_type
*/
protected $iCountTopicsCollectiveNew=0;
/**
* Число новых топиков в персональных блогах
*
* @var unknown_type
*/
protected $iCountTopicsPersonalNew=0;
/**
* Инициализация
*
*/
public function Init() {
$this->Viewer_AddBlocks('right',array('stream','tags','blogs'));
/**
* Подсчитываем новые топики
*/
$this->iCountTopicsCollectiveNew=$this->Topic_GetCountTopicsCollectiveNew();
$this->iCountTopicsPersonalNew=$this->Topic_GetCountTopicsPersonalNew();
$this->iCountTopicsFriendsNew=$this->PluginFriends_Friends_GetCountTopicsFriendsNew($this->User_GetUserCurrent()->getId());
$this->iCountTopicsNew=$this->iCountTopicsCollectiveNew+$this->iCountTopicsPersonalNew;
}
/**
* Регистрация евентов
*
*/
protected function RegisterEvent() {
$this->AddEventPreg('/^(page(\d+))?$/i','EventFriends');
}
/**********************************************************************************
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
**********************************************************************************
*/
/**
* Реализация евента
*
*/
protected function EventFriends() {
/**
* Меню
*/
$this->sMenuSubItemSelect='friends';
/**
* Передан ли номер страницы
*/
$iPage=$this->GetEventMatch(2) ? $this->GetEventMatch(2) : 1;
/**
* Получаем список топиков
*/
$aResult=$this->PluginFriends_Friends_GetTopicsFriends($this->User_GetUserCurrent()->getId(),1,10);
$aTopics=$aResult['collection'];
/**
* Формируем постраничность
*/
$aPaging=$this->Viewer_MakePaging($aResult['count'],$iPage,10,4,Router::GetPath('friends'));
/**
* Загружаем переменные в шаблон
*/
$this->Viewer_Assign('aTopics',$aTopics);
$this->Viewer_Assign('aPaging',$aPaging);
/**
* Устанавливаем шаблон вывода
*/
$this->SetTemplateAction('friends');
}
/**
* При завершении экшена загружаем переменные в шаблон
*
*/
public function EventShutdown() {
$this->Viewer_Assign('sMenuHeadItemSelect',$this->sMenuHeadItemSelect);
$this->Viewer_Assign('sMenuItemSelect',$this->sMenuItemSelect);
$this->Viewer_Assign('sMenuSubItemSelect',$this->sMenuSubItemSelect);
$this->Viewer_Assign('iCountTopicsNew',$this->iCountTopicsNew);
$this->Viewer_Assign('iCountTopicsFriendsNew',$this->iCountTopicsFriendsNew);
$this->Viewer_Assign('iCountTopicsCollectiveNew',$this->iCountTopicsCollectiveNew);
$this->Viewer_Assign('iCountTopicsPersonalNew',$this->iCountTopicsPersonalNew);
}
}
?>
Это так же самый обычный по виду экшен. Ключевые моменты:
— название PluginFriends_ActionFeed содержит указание на плагин Friends;
— класс экшена унаследован от ActionPlugin.
4. Добавляем шаблоны и пункт меню
Но, сейчас этот экшен работать не будет — нет пока шаблона для работы. С шаблонами есть маленький ньюанс — плагин может использоваться с различными шаблонами (skin). Поэтому чтобы у пользователей не возникало потом проблем с вашим плагином, плагин по умолчанию поддерживает мульти-skin. По умолчанию будет использован skin default. Поскольку наша задача не прорисовать как можно больше вариантов, а посмотреть на общую схему работы, то создаем директорию /templates/skin/default/ и туда вкладываем шаблон нашего экшена: actions/ActionFeed/friends.tpl.
Шаблон максимально простой:
{include file='header.tpl' menu='blog'}
{include file='topic_list.tpl'}
{include file='footer.tpl'}
Осталось последнее — создать пункт меню для попадания в Ленту друзей. Для того, чтобы это сделать нам нужно добавить доп. пункт в меню menu.blog.tpl. Мы сделаем это так: копируем файл menu.blog.tpl из шаблона new движка в директорию /plugins/friends/templates/skin/default/menu.blog.tpl. В этом файле в первую секцию добавим следующий код:
<li {if $sMenuSubItemSelect=='friends'}class="active"{/if}><div><a href="{router page='friends'}">{$aLang.plugin_friends_menu_title}</a>{if $iCountTopicsFriendsNew} +{$iCountTopicsFriendsNew}{/if}</div></li>
Именно это меню подключается в шаблоны в функции инициализации плагина Init() (об этом мы уже говорили):
$this->Viewer_AddMenu('blog',Plugin::GetTemplatePath(__CLASS__).'/menu.blog.tpl');
Последний штрих — языковой файл /templates/language/russian.php с единственной текстовкой:
<?php
/**
* Русский языковой файл плагина Friends
*/
return array(
'plugin_friends_menu_title' => 'Лента друзей'
);
?>
5. The End
Собственно и все. Кажется, ничего не забыл. Если остались вопросы — с радостью отвечу.
- +18
- 21 февраля 2010, 03:39
- kachayev
Алексей, была такая мелочь еще: конфиг-файл плагина обязательно должен был возвращать массив. Т.е. даже если мне просто надо было роутинг задать через Config::Set('router.page.xxx', ...);, то все равно приходилось возвращать пустой массив. Пишу в прошедшем времени, т.к. не проверял в последних релизах, а так и ставлю пустой массив на выходе. В общем-то, фигня, конечно, но лучше бы это дело как-то проверять при загрузке конфига.
Хороший плаг. Спасибо :)
Хотя, возможно, стоило бы для «руководства» взять плагин пообширнее охватывающий логику плагинов — с делегированием, например — это ж одна из основных фишек. Думаю в ближайшее время надо найти время что-нибудь из поделок для 0,31 переделать в плагин для 0,4, постараюсь захватить что-нибудь что еще не применяли в примерах.
Хотя, возможно, стоило бы для «руководства» взять плагин пообширнее охватывающий логику плагинов — с делегированием, например — это ж одна из основных фишек. Думаю в ближайшее время надо найти время что-нибудь из поделок для 0,31 переделать в плагин для 0,4, постараюсь захватить что-нибудь что еще не применяли в примерах.
На самом деле, для меня и делегирование, и все остальное — вполне «обыденно». Мне сложно сказать какая из этих частей функционала является более важной.
Поэтому сделал то, что «заказали» в прошлой публикации =)
Поэтому сделал то, что «заказали» в прошлой публикации =)
Я тоже не имел ввиду важность какой либо части, я имел ввиду другое — плагины они же на самом деле круче, чем просто способ не правя системные файлы встроить дополнительный функционал, так и надо это показать :) Ту же ленту друзей и на 0,31 можно вообще не затрагивая системные файлы сделать, ну да, только менюшку вписать в шаблон:)
Спасибо, теперь почти все для себя прояснил.
Один вопрос, как правильно прописывать делегирование внутри ?
Один вопрос, как правильно прописывать делегирование внутри ?
Потому что так сделано.
Для вывода количества новых вне экшена Friends, нужно задавать отдельно функционал в каждом из экшенов, где нужно это показывать. Например, с помощью механизма хуков.
Для вывода количества новых вне экшена Friends, нужно задавать отдельно функционал в каждом из экшенов, где нужно это показывать. Например, с помощью механизма хуков.
Уже понял, и сделал просто добавив в index и blog, жаль только что нельзя это сделать из плагина.
А про хуки примера не найдется?
А про хуки примера не найдется?
нельзя это сделать из плагинаМожно!
Для этого нужно внутри плагина создать хук, в котором получать количество новых записей в ленте, передавать их во Viewer. И повесить хук на shutdown экшенов index, blog
я у себя вот так сделал
<?php
/**
* Хук для плагина Friend Feed
*/
class PluginFriends_HookFriends extends Hook {
/**
* Регистрируем хук на action_event_index_after
*
* @return void
*/
public function RegisterHook() {
if ($this->User_IsAuthorization()) {
$this->AddHook("action_event_index_after", "setCountTopicsFriendsNew", __CLASS__);
}
}
/**
* Получаем количество новых записей в френдленте и передаем их в Viewer
*
* @param array $aVars
*/
function setCountTopicsFriendsNew($aVars) {
$this->Viewer_Assign('iCountTopicsFriendsNew', $this->PluginFriends_Friends_GetCountTopicsFriendsNew($this->User_GetUserCurrent()->getId()));
}
}
Можно немного подробнее, не могу найти где описано событие 'action_event_index_after'? В текущем движке 0.4 не нашел его, однако если такой хук добавить, то он работает в экшене индекс (вот тут большая просьба пояснить как, дефолтное событие?). Если повесить его на 'init_action' — работает в любом экшене.
А у плагина могут быть собственные блоки? Я имею ввиду, можно ли складывать плагиновские блоки вместе с остальными файлами плагина в site.ru/plugins/my_plugin/classes/blocks? Или он обязательно должны быть в site.ru/classes/blocks?
Да и еще одно интересно, может ли плагин в себе иметь скрипты для обработки ajax запросов. А то у мне пока выдает, что атаковали хакеры.
У кого-нибудь получалось прикрутить к плагину скрипты для обратки ajax запросов?
У кого-нибудь получалось прикрутить к плагину скрипты для обратки ajax запросов?
1) Ошибка в 49-ой строке файла /engine/classes/ActionPlugin.php
Т.к. $this->GetActionClass() содержит значение из $aConfig['route]['page'][{action}], то вместо
Соответственно появится ошибка и в 54-ой строке, где $aMatches[1] будет содержать не то, что нужно.
То же самое в 95-ой строчке.
2) Обычно делегирование нужно для модифицирования какого-то файла, поэтому он чаще всего лежит по аналогичному пути (в папке плагина) и имеет такое же имя, как и заменяемый аналог. На мой взгляд есть смысл автоматизировать прописывание этого пути.
Чаще всего будет представлять из себя что-то вроде
На мой взгляд, всё это лучше бы выглядело, например, так:
3) Я не нашел возможности делегировать темплейты, которые подключаются динамически — из других темплейтов. Например, header_top.tpl, paging.tpl, topic_list.tpl. Этого очень не хватает, есть ли возможность что-то придумать для таких ситуаций?
Т.к. $this->GetActionClass() содержит значение из $aConfig['route]['page'][{action}], то вместо
preg_match('/^Plugin([\w]+)_Action([\w]+)$/i',$this->GetActionClass(),$aMatches); должно бытьpreg_match('/^Action([\w]+)$/i',$this->GetActionClass(),$aMatches); иначе возникает ошибка.Соответственно появится ошибка и в 54-ой строке, где $aMatches[1] будет содержать не то, что нужно.
То же самое в 95-ой строчке.
2) Обычно делегирование нужно для модифицирования какого-то файла, поэтому он чаще всего лежит по аналогичному пути (в папке плагина) и имеет такое же имя, как и заменяемый аналог. На мой взгляд есть смысл автоматизировать прописывание этого пути.
Чаще всего будет представлять из себя что-то вроде
protected $aDelegates=array(
'action' =>array(
'ActionSettings' => 'PluginProtypes_ActionSettings',
'ActionRegistration' => 'PluginProtypes_ActionRegistration',
),
'template'=>array(
'actions/ActionSettings/profile.tpl' => '../../../plugins/protypes/templates/skin/new/actions/ActionSettings/profile.tpl',
'actions/ActionRegistration/index.tpl' => '../../../plugins/protypes/templates/skin/new/actions/ActionRegistration/index.tpl',
)
);
На мой взгляд, всё это лучше бы выглядело, например, так:
protected $aDelegates=array(
'action' =>array(
'ActionSettings' => '#__ActionSettings',
'ActionRegistration' => '#__ActionRegistration',
),
'template'=>array(
'actions/ActionSettings/profile.tpl' => '#__actions/ActionSettings/profile.tpl',
'actions/ActionRegistration/index.tpl' => '#__actions/ActionRegistration/index.tpl',
)
);
3) Я не нашел возможности делегировать темплейты, которые подключаются динамически — из других темплейтов. Например, header_top.tpl, paging.tpl, topic_list.tpl. Этого очень не хватает, есть ли возможность что-то придумать для таких ситуаций?
Интересная мысль! Только можно вообще без решетки, а просто с подчеркивания начинать. Т.е., если есть плагин MyPlugin и там делегирование описано так:
то подразумевается, что полная форма записи такая:
Вот только плохо, что сам модуль Plugin нельзя делегировать :(
'ActionSettings' => '_ActionSettings'то подразумевается, что полная форма записи такая:
'ActionSettings' => 'MyPlugin_ActionSettings'Вот только плохо, что сам модуль Plugin нельзя делегировать :(
'ActionSettings' => '_ActionSettings'Я только не пойму, зачем тогда вообще что-то указывать? =) Можно вспомнить Ruby On Rails и пойти по пути COC — если в качестве делегата ничего не указано — значит делегатов является одноименный ресурс из плагина, который производит делегирование.
С РоР не работал толком, поэтому для меня лично эта аналогия не катит. Если явно не указывать, то как? По имени самого плагина? Или перебирать экшены (модули, сущности), которые входят в состав плагина и сравнивать их с оригинальными компонентами?
Посмотри как я сделал это для модулей, экшенов и сущностей: в XML вместо
достаточно написать:
User
Фактически я указываю только название модуля, который хочу подменить и все. Рас я не указал явно делегат — значит считаем, что мой таргет имеет аналогичное с исходным расположение и название — добавляем в начало приставку и все.
<delegate>
<module>
<item>
<from>User</from>
<to>PluginTest_User</to>
</item>
</module>
</delegate>
достаточно написать:
User
Фактически я указываю только название модуля, который хочу подменить и все. Рас я не указал явно делегат — значит считаем, что мой таргет имеет аналогичное с исходным расположение и название — добавляем в начало приставку и все.
Насчет (1): ошибка была из-за того, что Router::GetActionClass() возращает имя экшена без учета делегирования.
Возможное решение: добавить на 162-ой строчке файла /engine/classes/Router.class.php сохранение нового названия экшена, если учитывается делегирование:
Создал тикет.
Возможное решение: добавить на 162-ой строчке файла /engine/classes/Router.class.php сохранение нового названия экшена, если учитывается делегирование:
$sActionClass=$this->Plugin_GetDelegate('action',$sActionClass);
self::$sActionClass = $sActionClass;Создал тикет.
Проверил, работает, спасибо.
Еще бы сделали чтобы можно было делегировать темплейт блоков, например block.stream.tpl, отдельно его элементы (block.stream_comment.tpl) можно делегировать, но саму основу нет.
Как понимаю всего то надо в smarty_insert_block строчку
у меня так заработало.
Еще бы сделали чтобы можно было делегировать темплейт блоков, например block.stream.tpl, отдельно его элементы (block.stream_comment.tpl) можно делегировать, но саму основу нет.
Как понимаю всего то надо в smarty_insert_block строчку
$sBlockTemplate = 'block.'.$aParams['block'].'.tpl';
заменить на
$sBlockTemplate = Engine::getInstance()->Plugin_GetDelegate('template','block.'.$aParams['block'].'.tpl');у меня так заработало.
ещё одно замечание. в текущей реализации ссылку на ленту друзей видят все пользователи (и гости в том числе), но у гостей она ведь не работает.
поэтому я добавил у себя проверку в шаблоне при выводе кнопки
и в экшене
может я что не так делаю. поправьте тогда
поэтому я добавил у себя проверку в шаблоне при выводе кнопки
{if $oUserCurrent}
<li {if $sMenuSubItemSelect=='friends'}class="active"{/if}>
<div><div><div>
<a href="{router page='friends'}">{$aLang.plugin_friends_menu_title}</a>{if $iCountTopicsFriendsNew} +{$iCountTopicsFriendsNew}{/if}
</div></div></div>
</li>
{/if}и в экшене
/**
* Инициализация
*
* @return void
*/
public function Init() {
// Закрываем страницу для неавторизированных пользователей
if(!$this->User_IsAuthorization()) {
return parent::EventNotFound();
}может я что не так делаю. поправьте тогда
ещё одно замечание. в текущей реализацииЯ знаю, что в этом плагине еще много чего можно доделать, он был написал для того, чтобы показать сам процесс создания плагина. А дальше — полет вашей фантазии и творчества.
большое спасибо за пример написания плагина
в экшене небольшая неточность:
в результате сабменю выводится от индекса, надо:
в экшене небольшая неточность:
<?php
class PluginFriends_ActionFeed extends ActionPlugin {
/**
* Главное меню
*
* @var unknown_type
*/
protected $sMenuHeadItemSelect='blog';
/**
* Меню
*
* @var unknown_type
*/
protected $sMenuItemSelect='index';
в результате сабменю выводится от индекса, надо:
protected $sMenuItemSelect='friends';
хорошо бы добавить вывод топиков только из тех блогов, на которые подписан. Это, мне кажется, куда важнее, чем топики друзей, т.к. человек подключился к 10-ти блогам, и потом может в отдельном разделе смотреть обновления их этих блогов.

- nickostyle
- 15 мая 2010, 02:10
- ↓
для версии 4.2 небольшая поправка… имя класса поправить PluginFriends_Friends ибо вылетает error'ка
Fatal error: Class 'PluginFriends_ModuleFriends' not found in X:\home\myblog\www\engine\classes\Engine.class.php on line 162
Спасибо автору! Только что реализовал у себя — вроде работает нормально (пока наполнения полноценного нету у сайта).
Очень полезная вещь. Странно, что такой функции у LS нету изначально. Хотя с другой стороны — хорошо, когда есть куда развиваться.
Еще раз спасибо!
Очень полезная вещь. Странно, что такой функции у LS нету изначально. Хотя с другой стороны — хорошо, когда есть куда развиваться.
Еще раз спасибо!
Товарищ, мы узнали что вам все же удалось реализовать написанное тут без багов, не могли бы вы поделится своей сборкой?
Мы это множество людей которые ищут готовое решение. Я лично столкнулся с тем что некоторые плагины стали вылетать. Пришлось править код для 4.2 Но так ни чего и не получилось. Хотел попросить тебя выложить архивом, есле у тебя получилась эта задумка.
Готов выложить свой вариант кода (всего плагина). Но думаю правильно будет сделать следующим образом:
1. скажите мне какие баги встречаются
2. я проверю свой код (и проект) на наличие таковых, чтобы не выкладывать код, который не факт, что работает правильно.
3. исправляю баги, если такие будут найдены.
4. выкладываю здесь ссылку на архив.
1. скажите мне какие баги встречаются
2. я проверю свой код (и проект) на наличие таковых, чтобы не выкладывать код, который не факт, что работает правильно.
3. исправляю баги, если такие будут найдены.
4. выкладываю здесь ссылку на архив.
Вы совершенно правы.
Могу сказать за себя, ставил все на 4.2
Не отображается в меню…
Пытался поставить в Профиль, но тоже какой-то косяк. Скорее всего кривые руки))… лечу их активным чтением документации.
Могу сказать за себя, ставил все на 4.2
'plugin_friends_menu_title' => 'Лента друзей'
Не отображается в меню…
Пытался поставить в Профиль, но тоже какой-то косяк. Скорее всего кривые руки))… лечу их активным чтением документации.
Вот ссылка на плагин в том виде, в котором он у меня работает.
www.ex.ua/view_storage/454673494809
Сразу скажу, что LS допиливал, поэтому не все может быть стандартно…
Попробуй.
www.ex.ua/view_storage/454673494809
Сразу скажу, что LS допиливал, поэтому не все может быть стандартно…
Попробуй.
Дело не в броузере. Если ты не выполнил вход (логин), то такое сообщение будет отображаться, поскольку в строке 60 оно пытается получить ID твоего текущего пользователя.
Вот и получается, что в FF работает (где есть сессия), а в Хроме — нет.
Как вариант решения — прятать ссылку на ленту для анонимных пользователей или при переходе на ленту предлагать выполнить вход (перебрасывать на страницу логина).
Вот и получается, что в FF работает (где есть сессия), а в Хроме — нет.
Как вариант решения — прятать ссылку на ленту для анонимных пользователей или при переходе на ленту предлагать выполнить вход (перебрасывать на страницу логина).
Дело не в броузере. Если ты не выполнил вход (логин), то такое сообщение будет отображаться, поскольку в строке 60 оно пытается получить ID твоего текущего пользователя.
Вот и получается, что в FF работает (где есть сессия), а в Хроме — нет.
Как вариант решения — прятать ссылку на ленту для анонимных пользователей или при переходе на ленту предлагать выполнить вход (перебрасывать на страницу логина).
Например в этом же файле в функции Init вначале добавить такой код:
Вот и получается, что в FF работает (где есть сессия), а в Хроме — нет.
Как вариант решения — прятать ссылку на ленту для анонимных пользователей или при переходе на ленту предлагать выполнить вход (перебрасывать на страницу логина).
Например в этом же файле в функции Init вначале добавить такой код:
/**
* Проверяем авторизован ли юзер
*/
if (!$this->User_IsAuthorization()) {
return Router::Action('login');
}
А как сделать, что бы на всех страницах было «Лента друзей +2»
сейчас появляется только когда захожу на test.ru/friends/
сейчас появляется только когда захожу на test.ru/friends/
Комментарии (101)
RSS свернуть / развернуть