Интеграция плагинов с админ-панелью LS

Одна из главных фишек новой админки, это удобная и проста интеграция с другими плагинами.
Теперь плагины могут встраивать свой интерфейс прямо внутрь админки.

Рассмотрим основные технические моменты. Есть два варианта интеграции:
  1. Визуальное управление конфигом плагина
  2. Встраивание функционала в интерфейс админки (для более сложных плагинов)

Визуальное управление конфигом плагина
Все что нужно сделать, это описать так называемую схему конфига. Она состоит из двух частей — описание всех параметров конфига и описание групп/разделов параметров, которые формируют визуальную группировку на странице редактирование параметров.
Описание всех параметров задается в конфиге плагина в специальном ключе $config_scheme$, например
$config['$config_scheme$'] = array(
	'per_page' => array(
		/*
		 * тип: integer, string, array, boolean, float
		 */
		'type' => 'integer',
		/*
		 * отображаемое имя параметра, ключ языкового файла относительно плагина, или просто текст
		 */
		'name' => 'Количество элементов на страницу',
		/*
		 * отображаемое описание параметра, ключ языкового файла относительно плагина, или просто текст
		 */
		'description' => 'config.per_page.description',
		/*
		 * валидатор (не обязательно)
		 */
		'validator' => array(
			/*
			 * тип валидатора, существующие типы валидаторов движка:
			 * Boolean, Compare, Date, Email, Number, Regexp, Required, String, Tags, Type, Url, + Array (специальный валидатор, см. документацию)
			 */
			'type' => 'Number',
			/*
			 * параметры, которые будут переданы в валидатор
			 */
			'params' => array(
				'min' => 1,
				'max' => 20,
				/*
				 * разрешить только целое число
				 */
				'integerOnly' => true,
				/*
				 * не допускать пустое значение
				 */
				'allowEmpty' => false,
			),
		),
	),
	'param_string_1' => array(
		'type' => 'string',
		'name' => 'config.param_string_1.name',
		'description' => 'config.param_string_1.description',
		'validator' => array(
			'type' => 'String',
			'params' => array(
				'min' => 5,
				'max' => 50,
				'allowEmpty' => true,
			),
		),
	),
);


Здесь в качестве ключей массива идут названия параметров конфига, далее описывается тип параметра, его название, описание и опции валидации. В качестве валидаторов можно использовать доступные валидаторы самого движка (модуль Validate). Также есть поддержка простых массивов (одномерное перечисление данных). Более подробно и типах параметров и их описании можно посмотреть здесь github.com/livestreet/lsplugin-admin/blob/master/config/config_scheme_sandbox.php
Далее необходимо описать разделы, делается это также в конфиге в параметре с ключом $config_sections$, например
$config['$config_sections$'] = array(
	/**
	 * Настройки раздела
	 */
	array(
		/**
		 * Название раздела
		 */
		'name' => 'config_sections.one',
		/**
		 * Список параметров для отображения в разделе
		 */
		'allowed_keys' => array(
			'per_page',
			'other.*'
		),
		/**
		 * Список параметров для исключения из раздела
		 */
		'excluded_keys' => array(
			'other.two',
		),
	),
	array(
		'name' => 'config_sections.two',
		'allowed_keys' => array(
			'param_string_*',
		),
	),
);

Здесь происходит перечисление разделов, для каждого раздела необходимо указать список ключей конфига, которые будут редактироваться. Обязательно должен быть объявлен хотя бы один раздел.

С описанием схемы закончили. Теперь если перейти на страницу списка активных плагинов и нажать кнопку «Конфигураци» у нужного плагина, то мы попадем на интерфейс редактирования конфига.

Встраивание функционала в интерфейс админки
Такая возможность необходима тем плагинам, которым нужна более сложная настройка и управление данными, чем просто редактирование конфига. Например, создание статей.
Необходимо создать экшен с именем ActionAdmin, например, PluginMy_ActionAdmin и обязательно наследовать его от специального класса PluginAdmin_ActionPlugin. Всё. Теперь можно смело писать свой функционал экшена, никаких отличий с обычными экшенами плагинов нет. Шаблоны экшена следует расположить в /actions/ActionAdmin/, причем можно это сделать как в текущем (во всех) скине плагина, так и в default или в admin_default, тогда темлейты для админки можно будет создать один раз и они не будут зависеть от текущего шаблона сайта.

Осталось только добавить свой пункт в меню админки. Для добавления пункта есть два варианта:
  1. Если у плагина только одна страница — добавлять лучше не в главное меню, а в подменю «Дополнительно»
  2. Если у плагина несколько страниц (создание статьи, список статей и т.п.), то лучше добавить раздел в главное меню со своими пунктами.
Меню в админке представляет собой набор объектов. Для изменения меню необходимо создать обработчик хука на событие init_action_admin. Для добавления пункта в меню «Дополнительно» в обработчике хука вставляем код:
$this->PluginAdmin_Ui_AddItemMenuAddition(Engine::GetEntity('PluginAdmin_Ui_MenuItem')->SetCaption('Список статей')->SetUrl('my'));

Новый пункт будет вести на страницу /admin/plugin/my/.
Пример добавления раздела в главное мню со своими пунктами:
/**
		 * Получаем объект главного меню
		 */
		$oMenu = $this->PluginAdmin_Ui_GetMenuMain();
		/**
		 * Добавляем новый раздел с пунктами
		 */
		$oMenu->AddSection(
			Engine::GetEntity('PluginAdmin_Ui_MenuSection')->SetCaption('Мой плагин')->SetName('my')->SetUrl('plugin/my')
				->AddItem(Engine::GetEntity('PluginAdmin_Ui_MenuItem')->SetCaption('Список статей')->SetUrl(''))
				->AddItem(Engine::GetEntity('PluginAdmin_Ui_MenuItem')->SetCaption('Создать')->SetUrl('create'))
		);


Пример плагина «Статьи» с интеграцией идет в комплекте с админкой — github.com/livestreet/lsplugin-admin/tree/master/example/plugins/article

35 комментариев

avatar
Обязательно должен быть объявлен хотя бы один раздел.
Вношу поправку: для плагинов разрешено не указывать вообще ни одного раздела и не писать ключ $config_sections$
avatar
по п.1: я бы предложил вынести это в отдельный файл (напр. config.admin.php)?
avatar
о желанию можно вынести в любой файл внутри каталога /config/, это давно поддерживается LS
avatar
А можно какой-нибудь пример встроенного плагина в админку. Например, плагина page для создания статических страниц.
avatar
извиняюсь, проглядел. Он в неактивных висел)
avatar
он не адаптирован к админке
пример плагина в самом конце топика
avatar
спасибо.
avatar
Добавьте пожалуйста в файле
/application/plugins/admin/classes/modules/plugins/Plugins.class.php
В строке 398 использование функции func_camelize:
было:
if (!file_exists($this->GetPluginRootFolderFileFullPath($sPluginCode, $this->GetFullFileNameForMainPluginClass($sPluginCode)))) {

стало:
if (!file_exists($this->GetPluginRootFolderFileFullPath($sPluginCode, func_camelize($this->GetFullFileNameForMainPluginClass($sPluginCode))))) {


Причина в том, что если создать для плагина папку import_topic то плагин админки проверяет наличие файла PluginImport_topic.class.php, а при активации плагина ищется файл PluginImportTopic.class.php.
Добавление функции func_camelize все решает.
Заранее спасибо.
avatar
исправлено
avatar
Спасибо :)
avatar
Где должны располагаться языковые файлы плагинов?
avatar
в /plugins/имя_плагина/templates/i18n в формате i18n
avatar
* с именем файла в формате i18n
avatar
/application/plugins/import_topic/templates/i18n/ru.php
разобрался.
avatar
Как в плагинах подключать языковые файлы js и где они должны находиться?
Подключил дефолтные сообщения в функции Init вот так:
$this->Viewer_AppendScript(Config::Get('path.framework.frontend.web').'/js/vendor/parsley/i18n/messages.ru.js');


Это правильно с точки зрения разработки плагина?
avatar
с языковыми js вопрос до конца еще не решен
но скрипты подключать, да, через Viewer_AppendScript
только если добавляется какой-то общедоступный скрипт, то его лучше именовать (параметр name), чтобы избежать дублей от других плагинов

ну а messages.ru.js мы подключим по дефолту в админке
avatar
только если добавляется какой-то общедоступный скрипт, то его лучше именовать (параметр name), чтобы избежать дублей от других плагинов
А можно тоже самое только примером, а то не совсем понял.

Создавая плагин дошел до модуля и был удивлен, что в примере article нет привычного маппера для работы с базой данной и добавления статьи в базу.
Когда можно будет ждать документации по ORM, желательно в формате ScreenCast? :)
avatar
А можно тоже самое только примером, а то не совсем понял.
второй параметр метода — массив:
$this->Viewer_AppendScript($sTemplateWebPath . 'js/parsley.js', array('name' => 'parsley'));

если другой плагин добавит этот же скрипт и укажет такое же имя (parsley) — дублей загружаемых скриптов не будет.
avatar
А почему бы не решить проблему так:
/framework/classes/modules/viewer/Viewer.class.php
Строка 819:
$this->aJsInclude['append'][md5($sJs)] = $sJs;

Таким образом человеческий фактор просто будет исключен.
avatar
одинаковые скрипты могут иметь разные пути, когда они поставляются вместе с плагином
avatar
А если два плагина назовут свои скрипты одинаково, например, array('name'=>'slider'), но при этом будут иметь разный функционал, что тогда произойдет?
Может что-то типа такого?
$this->aJsInclude['append'][md5(file_get_contents($sJs))] = $sJs;
avatar
от глупости никак не защититься
если это jquery плагин, то нужно по его названию, например, 'jquery.niceslider'
$this->aJsInclude['append'][md5(file_get_contents($sJs))] = $sJs;
скрипты могут отличаться версией, комментариями, минификацией кода и т.п.
avatar
Понял. Спасибо.
avatar
есть идея вытаскивать мд5 из имени файла, а не из пути.
avatar
при добавлении параметра типа array происходит вот что
avatar
не вставилось видое.
www.youtube.com/watch?v=8_5_qLY0Uk0
это создание настроек плагина. тип array
avatar
вставляемый текст покажите
avatar
/<div\sclass=«note»>.*[^>]/
любое текстовое значение, в котором встречается кавычка.
avatar
исправлено
avatar
Вместо названия плагина используется название папки (import_topic). Это специально сделано или это ошибка?
avatar
этот заголовок планировалось убрать, уберем
avatar
Спасибо.
avatar
Видеть имя папки тоже удобно. Может так «PluginName (PluginFolder)»?
avatar
добавлен вывод имени плагина
avatar
Чтобы в своем плагине для админки подключить редактор текста, кода в шаблоне приведенного ниже оказалось не достаточно:
{* Подключение редактора *}
{$sMediaTargetId=''}
{if $oTopicEdit}
    {$sMediaTargetId=$oTopicEdit->getId()}
{/if}
{include file='forms/editor.init.tpl' sMediaTargetType='topic' sMediaTargetId=$sMediaTargetId}


В экшене пришлось подключить стили и скрипты:
/**
* Скрипты для формы добавления топика
*/
$this->Viewer_AppendScript(Config::Get('path.application.web').'/frontend/common/js/media.js', array('name' => 'media'));
$this->Viewer_AppendScript(Config::Get('path.application.web')."/frontend/common/js/settings.js", array('name' => 'settings'));
$this->Viewer_AppendScript(Config::Get('path.framework.frontend.web')."/js/vendor/jquery.fileupload.js", array('name' => 'jquery.fileupload'));
/**
 * Стили для редактора
 */
$this->Viewer_AppendStyle(Config::Get('path.framework.frontend.web')."/js/vendor/markitup/skins/synio/style.css");
$this->Viewer_AppendStyle(Config::Get('path.framework.frontend.web')."/js/vendor/markitup/sets/synio/style.css");


Дополните пожалуйста файлы в /application/plugins/admin/classes/actions/ActionAdmin.class.php, чтобы было доступно сразу для всех плагинов админки, либо перенесите подключение необходимых файлов непосредственно в шаблон, так будет наверно более правильно.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.