Полное руководство по созданию плагинов в Joomla 1.5 (часть 1)
Плагины позволяют нам редактировать функциональность системы, без непосредственного редактирования существующего кода. Например, плагин можно использовать для обработки контента, перед выводом его на экран, расширить возможности поиска, или создать свой механизм авторизации. В этом уроке мы рассмотрим на примере, как заменить определенную стоку в статье с картинкой.
Введение
Когда мы начинаем создавать новый плагин, мы разбиваем создание на несколько частей. Так нам будет проще вникать в суть и удобнее тестировать плагин. В идеале, мы должны иметь более одного сервера, чтобы тестировать плагин (в частности его установку). Сначала мы создадим простейщий установщик. XML установщика опишит плагин, названный Foobar - My Extension.
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE install SYSTEM "http://dev.joomla.org/xml/1.5/plugin-install.dtd"><install version="1.5" type="plugin" group="foobar"><name>Foobar - My Extension</name><author>Имя автора</author><authorEmail>Email автора</authorEmail><authorUrl>Сайт автора</authorUrl><creationDate>Дата создания</creationDate><copyright>Копирайты</copyright><license>Лицензия</license><version>Версия плагина</version><description>Описание плагина</description><files><filename plugin="myextension">myextension.php</filename></files><params/></install>
Очень важно заметить параметр группы плагина. Вообще все плагины разделяются на логические группы. Вот список групп ядра Joomla: - authentication - content - editors - editors-xtd - search - system - user - xmlrpc Также как вы заметили, мы можем указать свою группу. Также в XMl-файле указывается очень важной информацией является параметр plugin. Этот параметр является уникальным в группе и идентифицирует наш плагин. Далее в таблице видны имена плагинов, которые уже заняты под ядро системы.
Группа Зарезервированные имена authentication gmail joomla ldap openid content emailcloak geshi loadmodule pagebreak pagenavigation sef vote editors none tinymce xstandard editors-xtd image pagebreak readmore search categories contacts content newsfeeds sections weblinks system cache debug legacy log remember user joomla xmlrpc blogger joomla
После того как вы создали XML файл myextension.xml, создайте файл myextension.php и положите их в каталог foobar. После чего заархивируйте в gz, .tar, .tar.gz, или zip (лучше все-так в zip). Заметьте, что файлы одного плагина не делятся на каталоги, потому что плагины состоят всего из двух файлов. После этого вы можете установить плагин. Но пока он не выполняет никаких действий.
События
Итак у нас должно быть создано событие, которое в дальнейшем будет обрабатываться плагином. Приложения Joomla используют глобальный объект, названный диспетчер событий (event dispatcher), для отправки событий зарегестрированным слушателям (listeners). Глобальный диспетчер событий - это объект JEventDispatcher, который является расширением абстрактного класса JObservable. В Joomla, слушателем может быть класс или функция. Когда мы используем класс слушателя, то этот класс должен быть расширением класса JPlugin. Именно расширением, для того чтобы наследовать основные методы класса. Итак, представьте что у нас есть компонент Foobar, отображающий некоторые записи из БД. Мы можем использовать событие onPrepareFoobar, которое происходит перед выводом записей. Чтобы добавить событие, мы записываем его с помощью метода triggerEvent() в диспетчер событий, который уже передает его слушателям. Метод triggerEvent() содержит два параметра: название события и массив аргументов переданных слушателям. Допустим мы добавляем событие onPrepareFoobar:
$dispatcher =& JDispatcher::getInstance();JPluginHelper::importPlugin('Foobar');$arguments = array(&$foobarData);$result = $dispatcher->trigger('onPrepareFoobar', $arguments);
Заметьте, что мы передаем $foobarData в виде ссылки, а второй параметр функции обязательно должен быть массивом. Теперь мы можем написать плагины, которые будут обрабатывать $foobarData.
Слушатель
Это одно из важнейших понятий. Вообще слушателями являются плагины, которые обрабатывают события переданные из диспетчера событий.
Регестрирование слушателей
Когда мы создаем новый плагин, если мы используем функции, мы должны информировать приложение о каждой функции и событии. Для этого нужно использовать метод приложений registerEvent(). Метод содержит два параметра: имя события и имя обработчика. Технически имя обработчика может быть именем класса. Например, в ядре Joomla компонент поиска использует плагины для поиска результата. Этот плагин ищет в статьях с помощью функции plgSearchContent() которая обрабатывает событие onSearch:
$mainframe->registerEvent('onSearch', 'plgSearchContent');
Обработка событий
Как уже говорилось ранее, мы можем использовать как функции, так и классы для обработки событий. Начнем мы наше изучение обработки событий с использования функций. Мы уже сделали заготовку плагина, названного My Plugin в группе Foobar и мы хотим обработать событие названное onPrepareFoobar. Перед тем как мы начнем создавать нашу функцию, мы должны дать ей название. Важно использовать следующее правило именований: слово plg, группа плагина, имя плагина, событие. Например, наша функция будет называться plgFoobarMyPluginPrepareFoobar. Например эту функцию мы можем использовать для обработки события:
$mainframe->registerEvent('onPrepareFoobar','plgFoobarMyPluginPrepareFoobar');/*** Переводит переданный параметр в верхний регистр.** @param Foobar Reference to a Foobar object*/function plgFoobarMyPluginPrepareFoobar(&$foobar) {$foobar->name = strtoupper($foobar->name);}
Самая важная часть в этой функции - это переданный параметр. Ранее мы передали параметр в виде массива. Каждый элемент массива обрабатывается плагином отдельно. Плагин состоящий из функции, так же может обрабатывать множественные события. Если мы хотим создать слушателя используя класс, для этого мы должны расширить класс JPlugin. Сначала мы должны разобраться как именовать класс слушателя. JPlugin требует специальное именование: слово plg, имя группы плагина, имя плагина. Например, плагин с именем myplugin в группе foobar должен называться plgFoobarMyplugin. Этот пример обрабатывает два события: onPrepareFoobar и onAfterDisplayFoobar.
// Импортируем класс JPluginjimport('joomla.event.plugin');/*** My Plugin event listener*/class plgFoobarMyplugin extends JPlugin{/*** Обрабатываем событие onPrepareFoobar** @param object Foobar to prepare*/function onPrepareFoobar(&$foobar){$foobar->name = JString::strtoupper($foobar->name);}/*** Обрабатываем событие onAfterDisplayFoobar** @param object Foobar which is being displayed* @return string XHTML to display after the Foobar*/function onAfterDisplayFoobar(&$foobar){return '<p>'.JText::_('Foobar Name converted to upper case byMy Plugin').'<p>';}}
В этом примере, как видите, вам не приходится самим регестрировать события. За вас все сделает фрэймворк Joomla. Главное правильно назвать класс и события. Когда мы импортируем плагин в Joomla, глобальный диспетчер событий автоматически смотрит классы слушателей и регестрирует их. Метод onAfterDisplayFoobar() вернет значение. Вы должны помнить, что ранее мы передали на обработку плагину массив. В этом примере видно как получить обратно уже обработанный массив.
$dispatcher =& JDispatcher::getInstance();JPluginHelper::importPlugin('Foobar');$arguments = array(&$foobarData);$result = $dispatcher->trigger('onPrepareFoobar', $arguments);$foobar->onAfterDisplayFoobar = trim(implode("\n", $result));
Это очень простой пример. Далее мы рассмотрим более сложные вещи.
Группы плагинов
Плагины делятся на различные группы. Каждая группа плагинов обрабатывает определенный набор событий. В ядре Joomla содержится 8 групп: authentication content editors editors-xtd search system user xmlrpc Далее мы рассмотрим каждую группу подробнее.
Authentication
Joomla поддерживает 4 различных методов авторизации: GMail Joomla! LDAP OpenID Также можно создать свои методы авторизации пользователя. В этой группе существует только один метод onAuthenticate. В плагине мы можем установить значение следующих свойств:
Свойство Описание birthdate Дата рождения пользователя country Страна пользователя email E-mail адрес пользователя error_message Сообщение об ошибке или отмена авторизации fullname ФИО gender Пол language Язык postcode Почтовый индекс status Статус авторизации timezone Часовой пояс username Логин
Свойство status используется для определения результата авторизации. Таблица содержит три константы, которые может содержать свойство status:
Константа Описание JAUTHENTICATE_STATUS_CANCEL Авторизация отменена JAUTHENTICATE_STATUS_FAILURE Ошибка авторизации JAUTHENTICATE_STATUS_SUCCESS Авторизация прошла успешно
По-умолчанию в Joomla опубликован только один плагин авторизации - Joomla!. Также вы можете опубликовать LDAP, GMAIL и OpenId. onAuthenticate
Описание Происходит, когда пользователь авторизируется на сайте Параметры username Логин password Пароль response Ссылка на объект JAuthenticationResponse
Content
Плагины группы content, позволяют обрабатывать элементы контента, прежде чем вывести его на экран. Наиболее часто используемое событие - это onPrepareContent. Это событие запускается самым первым. Поставим такую задачу- заменить все символы ":)" на картинку улыбающегося смайлика. Вот решение этой задачи:
defined('_JEXEC') or die('Restricted access');// регестрируем обработчик$mainframe->registerEvent('onPrepareContent','plgContentSmiley');/*** Заменим :) на смайлик.** @param object Content item* @param JParameter Content parameters* @param int Page number*/function plgContentSmiley(&$row, &$params, $page){$pattern = '/\:\)/';$icon = '<img src="/plugins/content/smiley.gif" />';$row->text = preg_replace($pattern, $icon, $row->text);}
Заметьте, что итоговые значения не нужно возвращаться, и параметр $row передается по ссылке. Рассмотрим подробнее атрибуты контента:
Атрибут Описание created дата создания в формате 0000-00-00 00:00:00. modified Дата последнего изменения в формате 0000-00-00 00:00:00 text основной контент элемента title заголовок элемента контента toc таблица контента
Теперь рассмотрим происходящие события. onAfterDisplayContent
Описание Создается xhtml строка после обработки контента Параметры row Ссылка на объект контента params ссылка на объект JParameter контента page Номер страницы Возвращает XHTML после отображения самого контента
onAfterDisplayTitle
Описание Создается xhtml строка после отображения заголовка страницы Параметры row Ссылка на объект контента params ссылка на объект JParameter контента page Номер страницы Возвращает XHTML после отображения заголовка страницы
onBeforeDisplayContent
Описание Создается xhtml строка перед отображением элемента text. Например плагин - рейтинг записи Параметры row Ссылка на объект контента params ссылка на объект JParameter контента page Номер страницы Возвращает XHTML перед выводом эелемента text
onPrepareContent
Описание Обрабатывает один элемент контента. Если вы собираетесь внести изменения в текст элемента, то вы должны использовать это событие. Параметры row Ссылка на объект контента params ссылка на объект JParameter контента page Номер страницы Возвращает Истина, если успешно
onPrepareContent
Описание Обрабатывает один элемент контента. Если вы собираетесь внести изменения в текст элемента, то вы должны использовать это событие. Параметры row Ссылка на объект контента params ссылка на объект JParameter контента page Номер страницы Возвращает Истина, если успешно
Editors
Пожалуй, самой сложный из всех основных плагинов - это редактор. Одним из основных редакторов является TinyMCE (http://tinymce.moxiecode.com/). TinyMCE это JavaScript редактор, который позволяет пользователю легко изменять данные в текстовом поле без знаний XHTML. Очень важно здесь отметить что кнопки под редактором создаются отдельными плагинами editors-xtd группы, о которых расскажу чуть позже. Приведу список самых популярных редактором за бугром: - ASBRU Web Content Editor - FCKeditor - wysiwygPro - XStandard - Yahoo Rich Text Editor Импортирование нового редактора задача не из легких. Зато если редактор уже встроен, то его очень просто подключать. Yahoo Rich Text Editor подает большие надежды. Это очень навороченный редактор, созданный на основе YUI (Yahoo User Interface). Про интерфейс Yahoo скоро начну вести отдельную серию статей. События плагинов: onDisplay
Описание Получить XHTML поле элемента формы Параметры name Уникальное название редактора content Инициируемые контент width Ширина редактора в пикселях height Высота редактора в пикселях col Ширина редактора в символах row Высота редактора в строках buttons Булево значение, служит чтобы скрыть или показать дополнительные кнопки; смотрите событие onCustomEditorButton из раздела editors-xtd этой статьи. Возвращает XHTML форма редактора
onGetContent
Описание Некоторый Javascript код, который возвращает контент Параметры editor Уникальное имя редактора Возвращает Запускает Javascript на стороне клиента, который вернет контент редактора. Код должен заканчиваться точкой с запятой.
onGetInsertMethod
Описание Запускаем javascript код, который определен функцией jInsertEditorText() Параметры name Уникальное имя редактора Возвращает Вставляем в редактор заданный текст в позицию курсора
onInit
Описание Инициализация запускается один раз независимо от колличества выхванных редакторов. Возвращает Необходимые функции по запуску редактора
onSave
Описание Запускаем javascript код, который необходим для сохранения редактора Параметры name Уникальное имя редактора Возвращает Javascript строку, которая запускается перед сохранением контента.
onSetContent
Описание Запускаем javascript код, который установит заданный контент в редакторе Параметры name Уникальное имя редактора HTML Новый контент редактора Возвращает Новый контент в редакторе
Editors-xtd
Эта группа плагинов используется для расширения функциональности редакторов, путем добавления к ним кнопок. К сожалению встроенный редактор xStandart не поддерживает эту группу плагинов. Существует только одно событие, связанные с этой группой, onCustomEditorButton. Поскольку существует только одно событие, связанное с этой группой, мы, будем использовать функции вместо работы с подклассами JPlugin. Этот пример показывает, каким образом мы можем добавить кнопку смайлика ":)" в редактор.
// no direct accessdefined('_JEXEC') or die('Restricted access');$mainframe->registerEvent('onCustomEditorButton','plgSmileyButton');/*** Кнопка смайликов** @name string Name of the editor* @return array Array of three elements: JavaScript action,Button name, CSS class.*/function plgSmileyButton($name){global $mainframe;// get the image base URI$doc =& JFactory::getDocument();$url = $mainframe->isAdmin() ? $mainframe->getSiteURL() : JURI::base();// get the JavaScript$js = "function insertSmiley(){jInsertEditorText(' :) ');}";$css = " .button1-left .smiley { background:url($url/plugins/editors-xtd/smiley1.gif)100% 0 no-repeat; }";$css .= "\n .button2-left .smiley { background: url('/$url/plugins/editors-xtd/smiley2.gif')100% 0 no-repeat; }";$doc->addStyleDeclaration($css);$doc->addScriptDeclaration($js);$button = array("insertSmiley()", JText::_('Smiley'),'smiley');return $button;}
В этом коде мы делаем два важных действия: мы определяем обработчик функции, и регистрируем ее в глобальном диспетчере событий. Переходя к функции plgSmileyButton() обратим внимание, что у нее есть параметр $name, который указывает на имя редактора. Он нужен для определения с каким редактором мы работает, так как их может быть несколько на одной странице. В самой функции мы этот параметр никак не используем. Мы создаем JavaScript и CSS код. Клиент будет выполнять JavaScript при нажатии кнопки. Также мы определяем два стиля CSS, чтобы сделать кнопку в разных местах (в админке и во фронте). В массиве $button мы возвращаем три элемента. Первый элемент - это JavaScript, который будет выполнен при нажатии кнопки. Вторым элементом является название кнопки. Третьим элементом является название класса CSS для кнопки. Также в плагине мы используем картинки, которые должны быть добавлены в xml файле:
<files><filename plugin="smiley">smiley.php</filename><filename>smiley1.gif</filename><filename>smiley2.gif</filename></files>
Перед тем как мы задействуем нашу кнопку в редакторе, обратим внимание на особо полезные методы редактора:
Метод Описание getContent JavaScript возвращает текст в редакторе save JavaScript сохраняет содержимое редактора (используется не во всех редакторах) setContent JavaScript устанавливает определенный контент
Все эти методы возвращают JavaScript строку. Мы можем использовать эти строки для создания скриптов, которые взаимодействуют с редактором. Покажу на примере, как пользоваться этими методами:
// получаем редактор$editor =& JFactory::getEditor();// вызываем javascript, который вызвращает контент$getContent = $editor->getContent($name);// строим javascript, который в окне отображает контент$js = 'var content = '.$getContent."\n".'alert(content);'
;
onCustomEditorButton
Описание Добавляет кнопку в редактор Параметры name Уникальное имя редактора Возвращает Массив из трех элементов: javascript, имя кнопки и css стиль
Search
Плагины группы search использюется для расширения основного компонента поиска и получения результатов поиска. Есть два события, связанные с этой группой, onSearch и onSearchAreas. Цель onSearchAreas трудновато понять. Приведу скриншот поиска:
В рамках поиска, пользователь может выбрать, где он хочет искать. В данном случае можно выбрать "Статьи", "Ссылки", "Контакты", "Категории", "Разделы", и "Ленты'. Когда мы инициируем onSearchAreas, мы выбираем в каком компоненте будет произведен поиск. Важно: Один плагин может искать в нескольких компонентах. Событие onSearch более косвенно, и срабатывает только когда происходит поиск. В итоге должен вернуться массив результатов. Реалзиция поиска будет зависеть от того, что вы ищете. onSearch
Описание Выполняет поиск и возвращает результаты Параметры text Искомая строка phrase Тип поиска 'any', 'all', или 'exact'. ordering Виды сортировки: 'newest', 'oldest', 'popular', 'alpha' (alphabetical), or 'category'. areas Раздел в котором ищем (основано на onSearchArea). Возвращает Ассоциативный массив со следующими полями: 'title', 'text', 'created', 'href', 'browsernav' (1 = открывать в новом окне), и 'section' (необязательное).
onSearchAreas
Описание Получить массив различных областях, которые могли быть обнаружены с помощью этого плагина. Каждый поиск плагин должны обратиться по крайней мере к одной области. Возвращает Ассоциативный массив различных областей для поиска.
System Есть четыре важных системных события. Вот их порядок: - onAfterInitialize - onAfterRoute - onAfterDispatch - onAfterRender onAfterDispatch
Описание Происходит после того, как была отправлена заявка
onAfterRoute
Описание Происходит после того как приложение инициализировано
onAfterDispatch
Описание Происходит когда приложение отрендерено, но еще не отправлено пользователю
onAfterRender
Описание Происходит после применения роутера
User
Плагины группы user позволяют выполнить дополнительную обработку в конкретных событиях связанных с пользователем. Это особенно полезно, когда эти плагины используются в сочетании с компонентом, который связан с таблицей # __users. Рассмотрим на примере событие onAfterUserStore. Это событие срабатывает после того, пользователь соханяет свои данные (срабатывает для новых и уже существующих пользователей). Этот пример показывает, как мы можем поддерживать другую таблицу, # __some_table, когда создан новый пользователь:
$mainframe->registerEvent('onAfterStoreUser','plgUserMaintainSomeTableStoreUser');/*** Add new rcord to #__some_table when a new user is created** @param array User attributes* @param boolean True if the user is new* @param boolean True if the user was successfully stored* @param string Error message* @return array Array of three elements: JavaScript action, Buttonname, CSS class.*/function plgUserMaintainSomeTableStoreUser($user, $isnew, $success,$msg){// if they are a new user and the store was successfulif ($isnew && $success){// add a record to #__some_table$db = JFactory::getDBO();$query = 'INSERT INTO '.$db->nameQuote('#__some_table').' SET '.$db->nameQuote('userid').' = '.$user['id'];$db->setQuery($query);$db->query();}}
onBeforeStoreUser
Описание Позволяет модифицировать данные пользователя перед сохранением Параметры user Ассоциативный массив с данными пользователя isnew Истина если пользователь новый
onAfterStoreUser
Описание Позволяет выполнять код, после того как данныен пользователя были сохранены Параметры user Ассоциативный массив с данными пользователя isnew Истина если пользователь новый success Истина в случае успешного сохранения msg Сообщение об ошибке если она имеется
onBeforeDeleteUser
Описание Позволяет нам выполнять дополнительную обработку до того, как пользователь будет удален. Это полезно для обновления неосновных таблиц, которые имеют отношение к ключевым таблицам #__users Параметры user Ассоциативный массив с данными пользователя
onAfterDeleteUser
Описание Позволяет выполнять код, после того как пользователь удален Параметры user Ассоциативный массив с данными пользователя success Истина в случае успешного удаления msg Сообщение об ошибке если она имеется
onLoginFailure
Описание Если логин или пароль введен неверно Параметры response JAuthenticationResponse обьект
onLoginUser
Описание Происходит при успешной авторизации пользователя Параметры user JAuthenticationResponse обьект remember Истина если пользователь хочет быть "запомненным" Возвращает Булево знчение ложь, если неуспешно
onLogoutUser
Описание Пользователь пытается выйти. В это время плагин "joomla" удаляет сессии. Параметры user JAuthenticationResponse обьект Возвращает Булево знчение ложь, если неуспешно
XML-RPC
XML-RPC - стандарт/протокол вызова удалённых процедур, основанный на XML, является прародителем SOAP, отличается исключительной простотой применения. XML-RPC, как и любой другой интерфейс RPC, определяет набор стандартных типов данных и команд, которые программист может использовать для доступа к функциональности другой программы, находящейся на другом компьютере в сети. Joomla! включает в себя XML-RPC сервер, который, как мы можем расширить с помощью плагинов. Плагины XML-RPC состоят из двух частей: обработчик события onGetWebServices, который возвращает массив поддерживающий веб-сервис вызовов, и статический класс или набор функций, которые управляют удаленным вызовом процедур. Если руки дойдут, расскажу об использовании XML-RPC в Joomla в отдельной статье. onGetWebServices
Описание Получить ассоциативный массив с описанием доступных методов веб-службы. Возвращает Ассоциативный массив в ассоциативном массиве, который определяет доступен ли сервис вызова.
Полное руководство по созданию плагинов в Joomla 1.5 (часть 1) - Генератор расширений Joomla и многое другое на нашем сайте посвященном работе расширений, компонентов, модулей, плагинов для линейки Joomla. Отправляйте ссылку на страницу своим друзьям и в социальные сети воспользовавшись графическими иконками выше.