Создание плагина joomla 4.x
Содержание
Структура плагина в Joomla! 1.5, 2.5 и 3.x была очень гибкой и мощной. Плагины могут быть использованы не только для обработки вызовов событий приложения и расширений ядра, но и для того, чтобы сделать сторонние расширения более мощными. В Joomla 4.x система диспетчера была переписана практически полностью. Это ещё больше увеличило гибкость, когда вы изменяете параметры, переданные как события, а также увеличило производительность плагинов.
В этом руководстве описаны основы разработки своего плагина. Большинство плагинов состоит из одного файла с кодом, но для правильной установки он должен быть упакован в установочный файл, который будет обработан установщиком Joomla.
Создание установочного файла
Так же как и все расширения Joomla, плагины могут быть легко установлены как .zip (поддерживается и .tar.gz), но при этом в архив должен быть включён корректно отформатированный XML файл.
В качестве примера приведём установочный XML файл для поискового плагина категорий
<?xml version="1.0" encoding="utf-8"?> <extension version="3.1" type="plugin" group="search" method="upgrade"> <name>plg_search_categories</name> <author>Joomla! Project</author> <creationDate>November 2005</creationDate> <copyright>Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_SEARCH_CATEGORIES_XML_DESCRIPTION</description> <files> <filename plugin="categories">categories.php</filename> </files> <languages> <language tag="en-GB">en-GB.plg_search_categories.ini</language> <language tag="en-GB">en-GB.plg_search_categories.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="search_limit" type="number" label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL" default="50" /> <field name="search_content" type="radio" label="JFIELD_PLG_SEARCH_ALL_LABEL" layout="joomla.form.field.radio.switcher" default="0" > <option value="1">JYES</option> <option value="0">JNO</option> </field> <field name="search_archived" type="radio" label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL" layout="joomla.form.field.radio.switcher" default="0" > <option value="1">JYES</option> <option value="0">JNO</option> </field> </fieldset> </fields> </config> </extension>
Как вы можете видеть, система схожа с другими установочными XML файлами Joomla. Вы только должны обратить внимание на запись group="xxx", тег
Если вы создаете плагин, который реагирует на существующие события ядра, атрибут group="xxx" должен быть изменен в соответствии с именем уже существующей папки для события, которое вы хотите использовать. Например, group="authentication" или group="user". Смотрите Plugin/Events полный список существующих категорий событий. При создании нового плагина для событий ядра важно, чтобы его название было уникальным, и чтобы он не конфликтовал с уже существующими плагинами, которые могут реагировать на то же событие, какое используете вы.
Если вы создаёте плагин для событий не ядра, то тег group="xxx" должен отличаться от существующих категорий ядра.
Совет: Если вы добавляете атрибут method="upgrade" к тэгу extension, то плагин можно будет устанавливать без удаления предыдущей версии. Все существующие файлы будут перезаписаны, но оставшиеся файлы удалены не будут.
Создание плагина
В Joomla 4 вы также можете иметь код пространства имен в своем плагине - пожалуйста, прочитайте Соглашения о пространстве имен в Joomla 4. Обратите внимание, что основной файл плагина не имеет пространства имен, а только файлы, работающие с полями и любой другой вспомогательный код.
Объектно-ориентированный подход к написанию плагинов включает в себя создание подклассов от CMSPlugin, базового класса, реализующего основные свойства плагинов. Для ваших методов доступны следующие свойства:
- $this->params: параметры, устанавливаемые администратором для этого плагина
- $this->_name: название плагина
- $this->_type: группа (тип) плагина
- $this->db: объект базы данных (db)
- $this->app: объект приложения (application)
Совет: Для использования $this->db и $this->app, CMSPlugin проверяет, существует ли свойство и что оно не приватное. Если вы хотите использовать дефолтные объекты, создайте неинстанцированные свойства класса плагина (например protected $db; protected $app;, там же где расположено protected $autoloadLanguage = true;). Свойства не будут существовать, пока не будут явно созданы.
В следующем примере кода PluginGroup представляет группу (тип) плагина, а PluginName представляет его имя. Обратите внимание, что имена классов и функций в PHP не чувствительны к регистру.
Здесь мы также реализуем SubscriberInterface, что является самым большим изменением по сравнению с Joomla 1.5-3.x. Вместо привычного подхода, когда имя функции автоматически определялось и было таким же, как имя события, этот подход позволяет задавать свои имена функции. Это позволяет нам показать, какие плагины реализуют какие функции, а так как парсинг публичных методов в PHP довольно медленный, это даёт значительное повышение производительности.
Здесь стоит заметить, что в линейке Joomla 4 существует слой совместимости, позволяющий работать плагинам, которые используют старую стратегию именования и не реализуют SubscriberInterface.
<?php // no direct access defined( '_JEXEC' ) or die; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Event\Event; use Joomla\Event\SubscriberInterface; class Plg<PluginGroup><PluginName> extends CMSPlugin implements SubscriberInterface { /** * Load the language file on instantiation * * @var boolean * @since 3.1 */ protected $autoloadLanguage = true; /** * Returns an array of events this subscriber will listen to. * * @return array */ public static function getSubscribedEvents(): array { return [ '<EventName>' => 'myFunctionName', ]; } /** * Plugin method is the array value in the getSubscribedEvents method * The plugin then modifies the Event object (if it's not immutable) */ public function myFunctionName(Event $event) { /* * Plugin code goes here. * You can access parameters via $this->params */ return true; } } ?>
Использование плагинов в вашем коде
Если вы создаете плагин для нового события, а не для встроенного события ядра, то не забудьте активировать плагин после установки. Перед ссылкой на ваш новый плагин должна стоять команда JPluginHelper::importPlugin().
Теперь, когда вы создали свой плагин, то вам наверняка захочется вызвать его в своем коде. Но не всегда: ядро Joomla имеет набор встроенных событий, которые вы можете использовать для регистрации плагина (тогда нижеописанное делать не нужно).
Новый подход в Joomla 4
Новый подход в Joomla 4 - получить диспетчер и отправить именованное событие.
use Joomla\CMS\Event\AbstractEvent; use Joomla\CMS\Factory; $dispatcher = Factory::getApplication()->getDispatcher(); // Here we create an event however as long as you implement EventInterface you can create your own // custom classes $event = AbstractEvent::create( '<EventName>', [ 'name' => $value, ] ); $eventResult = $dispatcher->dispatch('<EventName>', $event);
Если вы хотите позволить пользователю изменять значения, вы можете использовать результат события и getResults для его получения. Взгляните на
defined('_JEXEC') or die; use BadMethodCallException; use Joomla\CMS\Event\AbstractImmutableEvent; use Joomla\CMS\Table\TableInterface; /** * Event class for an event */ class MyCustomEvent extends AbstractImmutableEvent { /** * Constructor. * * @param string $name The event name. * @param array $arguments The event arguments. * * @throws BadMethodCallException */ public function __construct($name, array $arguments = array()) { if (!array_key_exists('myProperty', $arguments)) { throw new BadMethodCallException("Argument 'myProperty' is required for event $name"); } parent::__construct($name, $arguments); } /** * Setter for the myProperty argument * * @param mixed $value The value to set * * @return mixed * * @throws BadMethodCallException if the argument is not of the expected type */ protected function setMyProperty($value) { if (!empty($value) && !is_object($value) && !is_array($value)) { throw new BadMethodCallException("Argument 'src' of event {$this->name} must be empty, object or array"); } return $value; } }
Почему мы ввели класс вместо параметров? Это даёт возможность вводить собственные сеттеры и геттеры для свойств - на данный момент плагин может полностью изменить свойство по своему усмотрению, и для компонентов нет способа наложить какие-либо ограничения. Дополнительно разработчикам проще добавлять и убирать параметры в событии без потери обратной совместимости (так как вы теперь вызываете определённые методы и не привязаны к свойству, являющимся вторым аргументом вашей функкции).
Как достигнуть максимальной совместимости с Joomla 3
Если вы хотите вызвать событие по аналогии с удалённым J3.x JEventDispatcher, то ваш код должен выглядеть вот так:
$results = \Joomla\CMS\Factory::getApplication()->triggerEvent( '<EventName>', <ParameterArray> );
Важно отметить, что параметры должны быть массивом. Функция плагина сама по себе получает параметры как объект Event, если он реализует SubscriberInterface, и как индивидуальные значения, если нет. Но этот метод всегда возвращает массив, который возвращает плагин.
Обратите внимание на то, что если хотя бы один плагин в группе не реализует SubscriberInterface, то тогда свойство результата (так как одновременно является именованным параметром и результатом из плагина) используется как специальное свойство и не может быть использовано.
Оригинал: https://docs.joomla.org/J4.x:Creating_a_Plugin_for_Joomla/ru