Как написать свой плагин для joomla

Система плагинов в Joomla! 1.5 была очень мощной и гибкой. Плагины можно использовать не только для обработки событий, вызванных ядром приложения и его расширениями, но и для того, чтобы сделать сторонние дополнения более мощными и расширяемыми. Изменения в Joomla! 2.5/3.x в отличие от 1.5 в основном касаются имен событий.

В этом руководстве описаны основы разработки своего плагина. Большинство плагинов состоит из одного файла с кодом, но для правильной установки он должен быть упакован в установочный файл, который будет обработан установщиком Joomla!.

Создание установочного файла

Как и любые расширения для Joomla, плагины легко устанавливаются в виде .zip файлов (.tar.gz тоже поддерживается), но архив должен содержать правильно составленный XML файл. Вот пример XML файла для плагина поиска по категориям.

<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin" group="search">
	<name>plg_search_categories</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2013 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.1.0</version>
	<description>PLG_SEARCH_CATEGORIES_XML_DESCRIPTION</description>
	<files>
		<filename plugin="categories">categories.php</filename>
		<filename>index.html</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="text"
					default="50"
					description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
					label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
					size="5"
				/>

				<field name="search_content" type="radio"
					default="0"
					description="JFIELD_PLG_SEARCH_ALL_DESC"
					label="JFIELD_PLG_SEARCH_ALL_LABEL"
				>
					<option value="0">JOFF</option>
					<option value="1">JON</option>
				</field>

				<field name="search_archived" type="radio"
					default="0"
					description="JFIELD_PLG_SEARCH_ARCHIVED_DESC"
					label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL"
				>
					<option value="0">JOFF</option>
					<option value="1">JON</option>
				</field>
			</fieldset>

		</fields>
	</config>
</extension>

Как можно заметить, он похож на другие инсталляционные XML файлы для Joomla!. Нужно только обратить внимание на запись group="xxx" в разделе <extension>, а также на дополнительную информацию в разделе <filename> . Эта информация сообщает Joomla!, в какую папку копировать файл и в какую группу будет добавлен плагин.

Если вы создаете плагин, который реагирует на существующие события ядра, атрибут group="xxx" должен быть изменен в соответствии с именем уже существующей папки для события, которое вы хотите использовать. Например, group="authentication" or group="user". Смотрите Plugin/Events полный список существующих категорий событий. При создании нового плагина важно, чтобы его название было уникальным, и чтобы он не конфликтовал с уже существующими плагинами, которые могут реагировать на то же событие, какое используете вы.

Если вы создаете плагин реагировать на неосновные системные события вашего выбора для группы="ХХХ" тег должен отличаться от любого из существующих базовых категорий.

Совет: если вы добавляете атрибут method="upgrade" к тэгу extension, то плагин можно будет устанавливать без удаления предыдущей версии. Все существующие файлы будут перезаписаны, но оставшиеся файлы удалены не будут..

Создание плагинов

Объектно-ориентированный подход к написанию плагинов включает в себя создание подклассов от JPlugin, базового класса, реализующего основные свойства плагинов. Для ваших методов доступны следующие свойства:

Совет Для использования $this->db и $this->app, JPlugin проверяет, существуют ли свойства, и не закрытые ли они. Если предполагается использование объектов по умолчанию, создайте неинстанцированные свойства в классе плагина (к примеру protected $db; protected $app; в той же области видимости, что и protected $autoloadLanguage = true;). Свойства не будут существовать до тех пор, пока не будут созданы явно.

В следующем примере <PluginGroup> представляет группу (тип) плагина, а <PluginName> его название. Обратите внимание, что имена класса и функции в PHP не чувствительны к регистру.

<?php
// no direct access
defined( '_JEXEC' ) or die;

class plg<PluginGroup><PluginName> extends JPlugin
{
	/**
	 * Load the language file on instantiation. Note this is only available in Joomla 3.1 and higher.
	 * If you want to support 3.0 series you must override the constructor
	 *
	 * @var    boolean
	 * @since  3.1
	 */
	protected $autoloadLanguage = true;

	/**
	 * Plugin method with the same name as the event will be called automatically.
	 */
	 function <EventName>()
	 {
		/*
		 * Plugin code goes here.
		 * You can access database and application objects and parameters via $this->db,
		 * $this->app and $this->params respectively
		 */
		return true;
	}
}
?>

Использование плагинов в коде

Теперь, когда вы создали свой плагин, то вам наверняка захочется его вызвать в своем коде. Но делать это необязательно, ядро Joomla! имеет набор встроенных событий, которые вы можете использовать для запуска плагина. Тогда нижеописанное делать не нужно:

Чтобы запустить событие, используйте следующий код:

$dispatcher = JDispatcher::getInstance();
$results = $dispatcher->trigger( '<EventName>', <ParameterArray> );

Важно отметить, что параметры должны передаваться в массиве. Функция же в плагине будет получить параметры как отдельные значения. Возвращаемое значение будет состоять из массив возвращаемых значений из разных плагинов (поэтому он также может содержать многоуровневые массивы). Возвращаться будет массив значений из разных плагинов (этот массив может быть многоуровневым).

Если вы создаете плагин для нового события, а не для встроенного события ядра. то не забудьте активировать плагин после установки. Перед ссылкой на ваш новый плагин должна стоять команда JPluginHelper::importPlugin().

В прошлых частях мы рассмотрели, как работают плагины в Joomla и какие типы плагинов используются, а также рассмотрели несколько примеров плагинов. Теперь настало время попрактиковаться и создать свой собственный плагин.

Мы напишем простенький плагин, который будет использовать событие «onBeforeCompileHead». Это событие типа «system», которое появилось в версии Joomla 1.6, и позволяет нам изменять HTML-элемент head непосредственно перед его рендерингом. Таким образом, мы можем изменить любой HTML-элемент, который находится в head: meta, link или script.

Что будет делать наш плагин?

Событие «onBeforeCompileHead» вызывается в методе fetchHead() класса JDocumentRendererHtml. Этот метод читает информацию для HTML-элемента head из объекта документа и выводит её в буфер в HTML формате. Следующий код вызывает это событие:

// Trigger the onBeforeCompileHead event
$app = JFactory::getApplication();
$app->triggerEvent('onBeforeCompileHead');

Если мы посмотрим в исходный код HTML-страницы, то увидим неколько элементов meta внутри элемента head:

<meta name="robots" content="index, follow" />
<meta name="keywords" content="My keywords." />
<meta name="rights" content="My rights." />
<meta name="language" content="en-GB" />

Наш плагин будет добавлять мета-тег «revised», основываясь на параметре, который пользователь введет для плагина. Например, вывод нашего плагина может выглядеть следующим образом:

<meta name="revised" content="Dmitry Rekun, 16 октября 2012" />

где атрибут «content» — это текст, который указан в параметре плагина.

Чтобы этого достичь, нам необходимо понять, каким образом объект JDocumentHTML сохраняет данные для HTML-элемента head. Давайте проведем небольшое расследование.

В методе fetchHead() класса JDocumentRendererHead (где вызывается событие «onBeforeCompileHead»), мы видим, что переменная $document находится в сигнатуре метода. Это объект JDocumentHTML, у которого есть метод getHeadData(), который возвращает head-данные для документа или страницы. Если мы добавим команду var_dump($document->getHeadData()); в метод fetchHead() (например, непосредственно перед кодом, который вызывает событие), а потом посмотрим на страницу, то увидим длинный дамп вывода getHeadData(). Частью этого дампа будет следующее:

array
'title' => string 'Home' (length=4)
'description' => string 'My description.' (length=15)
'link' => string '' (length=0)
'metaTags' =>
           array
           'http-equiv' =>
                       array
                       'content-type' => string 'text/html' (length=9)
           'standard' =>
                       array
                       'robots' => string 'index, follow' (length=13)
                       'keywords' => string 'My keywords.' (length=12)
                       'rights' => string 'My rights.' (length=10)
                       'language' => string 'en-GB' (length=5)

Если мы сравним это с HTML кодом, который был показан ранее, мы увидим, что элементы meta с атрибутами «name» хранятся в объекте в качестве ассоциативного массива внутри элемента «standard», который находится внутри элемента «metaTags». Значение атрибута «name» является ключом (например, «robots»), а значение атрибута «content» является значением (например, «index, follow»).

Мы хотим, чтобы наш плагин добавлял новый мета-тег «revised» и его значением должен быть текст, который введет пользователь в форме «Менеджера плагинов». Мы хотим сохранить существующие мета-теги и добавить только новый.

Итак, алгоритм работы нашего плагина кода будет следующим:

  1. Прочитать существующие head-данные из документа. Это будет массив, который упоминался выше.
  2. Добавить элемент к ассоциативному массиву, который хранится в элементе «standard» внутри элемента «metaTags». Ключом для этого элемента будет «revised», а значением будут данные, которые пользователь ввел для параметра.
  3. Записать измененный массив в объект документа, используя метод setHeaderData() (по сути, он является зеркальным отражением метода getHeaderData()).
  4. Мы хотим это сделать только тогда, когда есть какие-то данные в параметре плагина. Если данных нет, то ничего не делаем.

Создаем установочный файл (файл манифеста)

Давайте не будем усложнять и назовем наш плагин просто — My Meta.

Создайте для него новую папку (например mymeta), а внутри неё создайте пустой файл index.html и файл mymeta.xml со следующим содержимым:


<?xml version="1.0" encoding="utf-8"?>
<extension version="2.5" type="plugin" group="system" method="upgrade">
    <name>PLG_SYSTEM_MYMETA</name>
    <author>Ваше имя</author>
    <creationDate>Дата создания</creationDate>
    <copyright>Информация о копирайте</copyright>
    <license>Информация о лицензии</license>
    <authorEmail>Ваш адрес электронной почты</authorEmail>
    <authorUrl>Ваш сайт</authorUrl>
    <version>1.0.0</version>
    <description>PLG_SYSTEM_MYMETA_XML_DESCRIPTION</description>
 
    <files>
        <filename plugin="mymeta">mymeta.php</filename>
        <filename>index.html</filename>
        <folder>language</folder>
    </files>
 
    <config>
        <fields name="params">
            <fieldset name="basic">
                <field name="revised" type="text"
                    description="PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC"
                    label="PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL"
                    filter="string"
                    default=""
                    size="50"
                />
            </fieldset>
        </fields>
    </config>
</extension>

Обратите внимание на строку:

<extension version="2.5" type="plugin" group="system" method="upgrade">

Атрибут «group» указывает на тип нашего плагина. Это значит, что после установки он будет размещен в директории plugins/system.

Также мы создали элемент fields с атрибутом «name», значение которого равно «params». Внутри мы расположили элемент fieldset «basic», который содержит необходимое нам поле. Все это находится внутри элемента config.

Если бы мы не создали элемент fields с атрибутом «name», то не имели бы возможности редактировать параметры плагина. Все дело в том, что для формы редактирования плагина используется файл разметки (administrator/components/com_plugins/views/plugin/tmpl/edit_options.php), который ищет элемент fields с именем «params» и включает содержащиеся в нем элементы fieldset в качестве опций формы.

Внутри элемента fieldset мы определили текстовое поле «revised». Таким образом, пользователь сможет указать свое значение для этого параметра. С помощью filter="string" мы вводим ограничение на допустимые символы в тексте. Фильтрация производится с помощью метода clean() класса JFilterInput.

Файл манифеста готов. Настало время написать непосредственно код плагина.

Создаем код плагина

Создайте в папке mymeta файл mymeta.php со следующим содержимым:


<?php
// Запрет прямого доступа.
defined('_JEXEC') or die;
 
/**
* Тестовый MyMeta плагин.
*/
class plgSystemMyMeta extends JPlugin
{
    function onBeforeCompileHead()
    {
        if ($this->params->get('revised')) 
        {
            $document = JFactory::getDocument();
            $headData = $document->getHeadData();
            $headData['metaTags']['standard']['revised'] = $this->params->get('revised');
            $document->setHeadData($headData);
        }
    }
}

Мы назвали наш класс plgSystemMyMeta согласно имеющемуся соглашению по именованию плагинов:

"plg" + <тип плагина> + <имя файла плагина>

В классе мы создали метод с названием onBeforeCompileHead() и его название в точности совпадает с названием события, на которое мы ориентируемся. Код метода довольно прост для понимания, так как мы уже разобрались со структурой массива метода getHeadData():

  1. Сначала мы проверяем, есть ли что-то в параметре «revised» нашего плагина. Если нет, то пропускаем обработку. К параметрам плагина мы обращаемся через свойство $params. Это объект типа JRegistry, в котором хранятся параметры плагина.
  2. Если что-то есть, то обрабатываем. Мы получаем объект документа и сохраняем результаты метода getHeadData() в переменной $headData.
  3. Мы создаем новый элемент ассоциативного массива под именем «revised» и устанавливаем его значение равным значению параметра плагина. Обратите внимание, наш элемент включен в массив, который в свою очередь включен в ещё один массив. Это мы видели в дампе вывода getHeadData().

Добавляем языковые файлы

Последним шагом перед проверкой нашего плагина будет добавление языковых файлов. Вспомните наш файл манифеста:

<files>
           <filename plugin="mymeta">mymeta.php</filename>
           <filename>index.html</filename>
           <folder>language</folder>
</files>

Элемент folder указывает на то, что в папке нашего плагина дожна быть подпапка «language».

Когда мы создаем плагин, мы можем выбрать: расположить языковые файлы в папке плагина или в папке adminstrator/languages. Для расширений рекомендуется располагать все файлы расширения отдельно от базовых файлов Joomla, поэтому языковые файлы расширения также предпочтительно располагать в папке расширения. Будем придерживаться этой практики и создадим папку language внутри папки mymeta. Внутри папки language создадим ещё две подпапки для каждого из языков: en-GB и ru-RU. Не забудьте разместить в них пустой файл index.html.

В нашем примере у нас будет четыре языковых файла, по два для каждого из языков:

en-GB.plg_system_mymeta.ini
en-GB.plg_system_mymeta.sys.ini

Будут располагаться в mymeta/language/en-GB.

ru-RU.plg_system_mymeta.ini
ru-RU.plg_system_mymeta.sys.ini

Будут располагаться в mymeta/language/ru-RU.

После установки плагина они будут располагаться в plugins/system/mymeta/language/en-GB/ и plugins/system/mymeta/language/ru-RU/ соответственно.

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

Файл plg_system_mymeta.ini является главным языковым файлом и содержит языковые строки, которые будут использоваться во время выполнения кода плагина, а также тогда, когда плагин будет открыт для изменения в Менеджере плагинов.

Содержимое файла en-GB.plg_system_mymeta.ini:

PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL="Revised сontent"
PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC="Meta revised text for content attribute."

Содержимое файла ru-RU.plg_system_mymeta.ini:

PLG_SYSTEM_MYMETA_FIELD_REVISED_LABEL="Содержимое revised"
PLG_SYSTEM_MYMETA_FIELD_REVISED_DESC="Текст для атрибута content meta-элемента revised."

Файл с .sys в названии используется для перевода имени, когда его просматривают в списке Менеджера расширений или в списке Менеджера плагинов. Также мы размещаем описание нашего плагина в этом файле для того, чтобы перевести описание в сообщении, которое отображается при установке плагина.

Содержимое файла en-GB.plg_system_mymeta.sys.ini:

PLG_SYSTEM_MYMETA="System - My Meta"
PLG_SYSTEM_MYMETA_XML_DESCRIPTION="Adds meta element with the name revised."

Содержимое файла ru-RU.plg_system_mymeta.sys.ini:

PLG_SYSTEM_MYMETA="Система - My Meta"
PLG_SYSTEM_MYMETA_XML_DESCRIPTION="Добавляет meta-элемент c именем revised."

Подробнее об использовании языковых файлах в расширениях вы можете прочитать в статье «Создание компонента для Joomla 2.5 — языковые файлы».

Все — теперь наш плагин полностью готов. Давайте протестируем его работу.

Тестируем плагин

Запакуйте содержимое папки mymeta в архив (zip, tar, tar.gz, bz2) или скачайте его напрямую с нашего сайта и установите, используя Менеджер расширений.

Зайдите в «Расширения – Менеджер плагинов» и в фильтре «- выбор типа -» выберите «system». В списке вы должны увидеть наш плагин «Систем – My Meta». Кликните на него, и вы попадете в редактирование параметров плагина:

Создание плагина для Joomla 2.5 - экран редактирования плагина

Измените состояние плагина на «Включено», введите текст для содержимого «revised» и сохраните. Теперь пройдите на главную страницу и просмотрите исходный код с помощью браузера. Вы увидите что-то похожее на это:

<meta name="robots" content="index, follow" />
<meta name="keywords" content="My keywords." />
<meta name="rights" content="My rights." />
<meta name="language" content="en-GB" />
<meta name="revised" content="Dmitry Rekun, 16 октября 2012 года" />
<meta name="description" content="My description." />

Мы видим, что мета-тег «revised» присутствует в списке мета-тегов. В качестве финального теста, вернитесь в «Менеджер плагинов» и сотрите содержимое параметра «revised». Теперь сделайте рефреш страницы и проверьте исходный код. Мета-тег с именем «revised» должен был пропасть, так как мы стерли его содержимое в параметрах плагина.

Поздравляю! Вы успешно справились с созданием собственного плагина для Joomla. В следующей части мы рассмотрим, каким образом можно переопределить базовые классы Joomla с помощью плагина.

{phocadownload view=file|id=151|target=s}

Как создать плагин для Joomla 4

  1. Введение в создание собственного плагина для CMS Joomla 4
  2. Создание установочного файла плагина для CMS Joomla 4
  3. Создание плагина для CMS Joomla 4
  4. Использование готовых плагинов. Как вызвать плагин в коде Joomla 4
    1. Новый способ работы с плагинами в CMS Joomla 4
    2. Как добиться максимальной совместимости с Joomla 3

Введение в создание собственного плагина для CMS Joomla 4

Структура плагина для Joomla! 1.5, 2.5 и 3.x были очень гибкими и мощными. Плагины могут использоваться не только для обработки событий, вызванных основным приложением и расширениями, но и для расширения имеющихся и расширения сторонних расширений. В Joomla 4.x была переписана большая часть системы диспетчеризации, чтобы еще больше повысить гибкость при изменении параметров, передаваемых в виде событий, одновременно повышая производительность плагинов.

Это руководство должно предоставить вам основы того, что нужно знать, чтобы разработать свой собственный плагин. Большинство плагинов состоят всего из одного файла кода, но для правильной установки кода плагина он должен быть упакован в установочный пакет с файлом-манифестом, который может быть обработан установщиком Joomla.

Создание файла-манифеста плагина для CMS Joomla 4

Как и все расширения в 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>[email protected]</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-файлы CMS Joomla. Вам нужно только обратить внимание на запись group="xxx" в теге <extension> и расширенную информацию в теге <filename>. Эта информация сообщает Joomla, в какую папку скопировать файл и в какую группу следует добавить плагин.

Если вы создаете плагин, который реагирует на существующие основные события, атрибут group="xxx" будет изменен, чтобы отразить имя существующей папки плагина для типа события, который вы хотите расширить. Например, group="authentication" или group="user". Полный список существующих категорий основных событий см. в разделе Плагин/События официальной документации Joomla (Прим.переводчика: Который по какой-то причине отсутствует и дополнительно смотреть фактически нечего). При создании нового плагина для реагирования на основные события важно, чтобы имя вашего плагина было уникальным и не конфликтовало ни с одним из других плагинов, которые также могут реагировать на основное событие, которое вы хотите обслуживать.

Если вы создаете плагин для реагирования на неосновные системные события, ваш выбор для тега group="xxx" должен отличаться от любой из существующих основных категорий.

СОВЕТ: Если вы добавите атрибут method="upgrade" в тег extension, этот плагин можно установить без удаления более ранней версии. Все существующие файлы будут перезаписаны, но старые файлы не будут удалены.

Создание плагина для CMS Joomla 4

В Joomla 4 вы также можете иметь код пространства имен в своем плагине — пожалуйста, прочитайте Соглашения о пространстве имен в Joomla 4. Обратите внимание, что основной файл плагина не имеет пространства имен, а только файлы, работающие с полями и любой другой вспомогательный код.

Объектно-ориентированный способ написания плагинов включает в себя написание подкласса CMSPlugin, базового класса, реализующего основные свойства плагинов. В ваших методах доступны следующие свойства:

  • $this->params: параметры, установленные для этого плагина администратором
  • $this->_name: имя плагина
  • $this->_type: группа (тип) плагина
  • $this->db: объект db (базы данных)
  • $this->app: объект приложения

СОВЕТ: Чтобы использовать $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
// всем, кто не Joomla - кыш и брысь!
defined( '_JEXEC' ) or die;

use JoomlaCMSPluginCMSPlugin;
use JoomlaCMSEventEvent;
use JoomlaEventSubscriberInterface;

class Plg<PluginGroup><PluginName> extends CMSPlugin implements SubscriberInterface
{
	/**
	 * Загрузите языковой файл при создании экземпляра
	 *
	 * @var    boolean
	 * @since  3.1
	 */
	protected $autoloadLanguage = true;

	/**
	 * Возвращает массив событий, которые будет прослушивать этот подписчик.
	 *
	 * @return  array
	 */
	public static function getSubscribedEvents(): array
	{
		return [
			'<EventName>' => 'myFunctionName',
		];
	}

	/**
	 * Метод плагина - это значение массива в методе getSubscribedEvents
	 * Затем плагин изменяет объект события (если он не является неизменяемым)
	 */
	 public function myFunctionName(Event $event)
	 {
		/*
		 * Код плагина тута!
		 * Вы можете получить доступ к параметрам через $this->params
		 */
		return true;
	}
}
?>

Если вы создаете плагин для нового, непрофильного события, не забудьте активировать его после установки в админке. Перед любой ссылкой на ваш новый плагин используйте команду JPluginHelper::importPlugin().

Теперь, когда вы создали свой плагин, вы, вероятно, захотите вызвать его в своем коде. Возможно, нет: ядро Joomla имеет ряд встроенных событий, на которые вы можете зарегистрировать свой код плагина (и в этом случае вы можете игнорировать этот раздел).

Новый способ работы с плагинами в CMS Joomla 4

Новый способ сделать это в Joomla 4 — это получение диспетчера и отправить именованное событие.

use JoomlaCMSEventAbstractEvent;
use JoomlaCMSFactory;

$dispatcher = Factory::getApplication()->getDispatcher();

// Здесь мы создаем событие, однако, пока вы реализуете EventInterface, 
// вы можете создавать свои собственные пользовательские классы.
$event = AbstractEvent::create(
	'<EventName>',
	[
		'name' => $value,
	]
);

$eventResult = $dispatcher->dispatch('<EventName>', $event);

Если вы хотите разрешить пользователю изменять значения, вы можете использовать результат события и получить результаты из getResults. Вы можете делать так:

defined('_JEXEC') or die;

use BadMethodCallException;
use JoomlaCMSEventAbstractImmutableEvent;
use JoomlaCMSTableTableInterface;

/**
 * Класс события для события
 */
class MyCustomEvent extends AbstractImmutableEvent
{
	/**
	 * Constructor.
	 *
	 * @param   string  $name       Название события.
	 * @param   array   $arguments  Аргументы события.
	 *
	 * @throws  BadMethodCallException
	 */
	public function __construct($name, array $arguments = array())
	{
		if (!array_key_exists('myProperty', $arguments))
		{
			throw new BadMethodCallException("Аргумент 'MyProperty' требуется для события $name");
		}

		parent::__construct($name, $arguments);
	}

	/**
	 * Установщик для аргумента myProperty
	 *
	 * @param   mixed  $value  Значение для установки
	 *
	 * @return  mixed
	 *
	 * @throws  BadMethodCallException  если аргумент не имеет ожидаемого типа
	 */
	protected function setMyProperty($value)
	{
		if (!empty($value) && !is_object($value) && !is_array($value))
		{
			throw new BadMethodCallException("Аргумент 'src' события {$this->name} должен быть пустым, объектом или массивом");
		}

		return $value;
	}
}

Почему мы ввели этот класс имени над параметрами? Что ж, это облегчает введение пользовательских установщиков и геттеров для свойств — в настоящее время плагин может либо полностью изменить свойство по своему усмотрению — для компонентов нет никакого способа налагать какие-либо ограничения. Кроме того, это значительно облегчает разработчикам добавление и удаление параметров в событии без серьезных b/c проблем (поскольку теперь вы вызываете определенные методы и не подчиняетесь свойству, являющемуся 2-м аргументом вашей функции).

Как добиться максимальной совместимости с Joomla 3

Если вы хотите вызвать событие аналогично устаревшему J3.x JEventDispatcher, то используйте такой код:

$results = JoomlaCMSFactory::getApplication()->triggerEvent( '<EventName>', <ParameterArray> );

Важно отметить, что параметры должны быть в массиве. Сама функция плагина получит параметры в виде объекта события, если она реализует SubscriberInterface, и в виде отдельных значений, если это не так, но этот метод всегда будет возвращать массив, возвращаемый плагином.

Обратите внимание, что если КАКОЙ-ЛИБО плагин в группе не реализует интерфейс SubscriberInterface, то свойство result (как именованный параметр, так и результат плагина) используется как специальное свойство и не может быть использовано иначе.

Перевод с английского официальной документации CMS Joomla 4:
https://docs.joomla.org/J4.x:Creating_a_Plugin_for_Joomla

Заберите ссылку на статью к себе, чтобы потом легко её найти!
Выберите, то, чем пользуетесь чаще всего:

Содержание

  • 1 Создание установочного файла
  • 2 Создание плагина
  • 3 Использование плагинов в вашем коде
    • 3.1 Новый подход в Joomla 4
    • 3.2 Как достигнуть максимальной совместимости с Joomla 3

Структура плагина в 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», тег и расширенную информацию в теге . Эта информация говорит Joomla, в какую папку скопировать файл и в какую группу должен быть добавлен плагин.

Если вы создаете плагин, который реагирует на существующие события ядра, атрибут 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 JoomlaCMSPluginCMSPlugin;
use JoomlaEventEvent;
use JoomlaEventSubscriberInterface;

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 JoomlaCMSEventAbstractEvent;
use JoomlaCMSFactory;

$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 JoomlaCMSEventAbstractImmutableEvent;
use JoomlaCMSTableTableInterface;

/**
 * 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 = JoomlaCMSFactory::getApplication()->triggerEvent( '<EventName>', <ParameterArray> );

Важно отметить, что параметры должны быть массивом. Функция плагина сама по себе получает параметры как объект Event, если он реализует SubscriberInterface, и как индивидуальные значения, если нет. Но этот метод всегда возвращает массив, который возвращает плагин.

Обратите внимание на то, что если хотя бы один плагин в группе не реализует SubscriberInterface, то тогда свойство результата (так как одновременно является именованным параметром и результатом из плагина) используется как специальное свойство и не может быть использовано.

Оригинал: https://docs.joomla.org/J4.x:Creating_a_Plugin_for_Joomla/ru

Плагины Joomla. Подробный разбор простым языком

Если вы работаете с Joomla, то, скорее всего, знаете, что в этой CMS существуют несколько видов расширений. Это компоненты, модули, шаблоны и плагины. С первыми тремя типами расширений всё понятно. А вот для чего нужны плагины многие, я уверен, не очень хорошо понимают.

В этой большой статье я подробно простым языком расскажу о том, что такое плагины Joomla, для чего они нужны, какие типы плагинов бывают, как они работают, как создать собственный плагин, когда и зачем это необходимо делать.

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

Для начала давайте разберемся с тем, что же вообще такое плагин Joomla. Вообще, если отбросить шаблоны, в Joomla есть три типа расширений, которые увеличивают функциональность сайта. Это:

  • Компоненты
  • Модули
  • Плагины

Компоненты Joomla позволяют создать приложения с широким функционалом. Если вам нужны уникальные типы контента, отдельные страницы сайта с контентом этих типов, уникальные URL для таких страниц – ваш выбор компонент. Примеры компонентов: форум, интернет-магазин, социальная сеть, тикет-система, система бронирования и т.п.

Модули Joomla позволяют создать отдельный блок, который будет показываться на тех или иных страницах сайта. Если вам нужно показать пользователям баннер, форму авторизации, навигатор сайта, меню, то нужно использовать модуль.

Плагины Joomla, на первый взгляд, кажутся каким-то обособленным и непонятным типом расширения. Это происходит в первую очередь потому, что плагин нельзя увидеть на сайте также просто как модуль. Плагин иногда вообще не имеет визуальной проекции. Но у плагинов тоже есть свой тайный смысл. Раз разработчики Joomla выделили плагины в отдельный тип расширений, значит, это было сделано не просто так.

Чтобы понять, что же такое плагины Joomla и для чего они необходимы, нужно разобраться еще с одним термином, который имеет непосредственное отношение к плагинам. Это хак ядра Joomla.

Хак ядра Joomla (или просто «Хак») – внесение изменений в код системных файлов Joomla, которые могут быть стерты при обновлении CMS.

Из определения должно быть понятно, чем плохо вносить хаки, но всё-таки поясню.

В Joomla есть файлы ядра (первоначальные) – те, которые поставляются в архиве с CMS, и файлы установленных расширений (добавленные) – те, которые появляются после установки администратором расширений или других манипуляций с сайтом. Разделение файлов на такие группы не обязательно связано с их назначением. Например, файлы модуля Joomla могут являться как файлами ядра (когда модуль поставляется вместе с Joomla), так и файлами установленных расширений (когда вы сами установили этот модуль в Joomla). Это же относится и к другим типам расширений.

Теперь представьте, что вы внесли некоторое изменение в файл ядра (создали хак). В случае обновления Joomla (которые, кстати, выходят довольно часто) существует вероятность, что разработчики в обновленной версии внесли изменения в тот же самый файл, в который внесли их и вы. Что произойдет в этом случае? Файл с вашими изменениями (с хаком) просто будет перезаписан файлом из обновленной версии. При этом все изменения, которые вы вносили, будут удалены. Не очень приятно, не правда ли?

Интересно еще и другое. Файлы установленных расширений тоже являются системными файлами ядра, но только уже не Joomla, а данных расширений. Например, в случае, если вы установили модуль, внесли в его файлы изменения, а затем вышло обновление модуля и вы обновили его на сайте, с вашими изменениями произойдет ровно то же самое, что и в случае хака Joomla – они будут стерты при перезаписи.

Вы спросите: «Как же тогда вообще вносить изменения в файлы, если это необходимо?». Одним из решений описанной выше проблемы, являются, так называемые, переопределения макетов и альтернативные макеты. Они работают хорошо, но, к сожалению, как понятно из названия, переопределяют только макеты отображения, но не функционал ядра.

Другим решением как раз и являются плагины.

Плагин позволяет вставить в некотором месте выполнения программы (php-скрипта) свой собственный код, который будет изменять или расширять функционал этой программы.

Интересно, что при использовании плагина, нам не нужно будет вносить изменения в файлы ядра. Вы спросите: «Как такое возможно?». Это будет важный и правильный вопрос.

Я предлагаю представлять плагин, как флешку для компьютера. Joomla же, в данном случае, это сам компьютер. Также плагином может быть любое другое устройство, которое вы вставляете в разъем USB. Что при этом происходит? С помощью дополнительного устройства вы расширяете функционал компьютера, не внося в его конструкцию никаких изменений. Вы вставили флешку – появился дополнительный диск, вы вставили колонки – компьютер теперь может воспроизводить звук. Компьютер может работать как с этим устройством, так и без него. Наличие этого устройства необязательно. Сам компьютер от него никак не изменяется.

Плагины в Joomla работают аналогичным образом – они расширяют функционал, не обязательно, видимый, путем включения своего кода  в код основной системы. А роль разъема USB, который используется для соединения компьютера и флешки, в Joomla выполняют так называемые триггеры (triggered events).

Триггеры для плагинов Joomla

Триггер в Joomla, представляет собой «разъем», в который может подключиться плагин и выполнить свой код. В коде Joomla это выглядит примерно следующим образом:

Код Joomla;
Код Joomla;
Выполнить код плагинов определенного типа, если такие существуют в CMS (это триггер);
Код Joomla;
Код Joomla;

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

Таким образом, с помощью плагинов и триггеров, мы получаем в Joomla аналог разъема USB. Разница лишь в том, что в Joomla много мест, где вставлены триггеры (строчки вызова выполнения плагинов). Разработчики Joomla не знают, где именно вам потребуется вызвать код плагина, но они стараются предугадать места, где вам это может потребоваться с наибольшей вероятностью.

В Joomla существует известный набор триггеров, расположенных в разных частях CMS. Все триггеры  разбиты на группы. Каждая такая группа характеризует один из типов плагинов.

Типы плагинов Joomla и существующие наборы их триггеров

Каждый плагин Joomla относится к определенному типу. Тип плагина указывает на место его исполнения в CMS и примерный функционал. Кроме того, каждый тип плагинов имеет предопределенный набор триггеров.

Типы плагинов Joomla

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

Тип «Authentication»

Плагины, которые выполняются при авторизации пользователя.

Триггеры:

  • onUserAuthenticate

Тип «Captcha»

Плагины, которые выполняются в процессе работы с капчами.

Триггеры:

  • onInit
  • onDisplay
  • onCheckAnswer

Тип «Content»

Плагины, которые выполняются в процессе работы с контентом (создания, изменения, сохранения, удаления, отображения и др.).

Триггеры:

  • onContentPrepare
  • onContentAfterTitle
  • onContentBeforeDisplay
  • onContentAfterDisplay
  • onContentBeforeSave
  • onContentAfterSave
  • onContentPrepareForm
  • onContentPrepareData
  • onContentBeforeDelete
  • onContentAfterDelete
  • onContentChangeState
  • onContentSearch
  • onContentSearchAreas

Тип «Editors»

Плагины, которые выполняются в процессе работы с текстовыми редакторами Joomla.

Триггеры:

  • onInit
  • onSave
  • onSetContent
  • onDisplay
  • onGetContent
  • onGetInsertMethod

Тип «Editors-XTD»

Плагины, которые выполняются в процессе работы с текстовыми редакторами Joomla (добавление дополнительных кнопок под редактором).

Триггеры:

  • onDisplay

Тип «Extensions»

Плагины, которые выполняются в процессе работы с расширениями Joomla (установка, обновление, удаление и др.).

Триггеры:

  • onExtensionAfterInstall
  • onExtensionAfterUninstall
  • onExtensionAfterUpdate
  • onExtensionBeforeSave
  • onExtensionAfterSave

Тип «Finder»

Плагины, которые выполняются в процессе работы умного поиска. Чаще всего сюда попадают плагины, индексирующие различный контент для умного поиска.

Триггеры:

  • onFinderCategoryChangeState
  • onFinderChangeState
  • onFinderAfterDelete
  • onFinderBeforeSave
  • onFinderAfterSave

Тип «Quick Icons»

Плагины, которые выполняются в процессе создания иконок (модуль quickions) на главной странице админки.

Триггеры:

  • onGetIcons

Тип «System»

Плагины, которые выполняются в ходе генерации любой страницы сайта.

Триггеры:

  • onAfterInitialise
  • onAfterRoute
  • onAfterDispatch
  • onAfterRender
  • onBeforeRender
  • onBeforeCompileHead

Тип «User»

Плагины, которые выполняются в процессе работы с пользователями (авторизация, регистрация, изменение информации о пользователе и др.).

Триггеры:

  • onUserAuthorisation
  • onUserAuthorisationFailure
  • onUserBeforeSave
  • onUserAfterSave
  • onUserBeforeDelete
  • onUserAfterDelete
  • onUserLogin
  • onUserLoginFailure
  • onUserAfterLogin
  • onUserLogout
  • onUserBeforeSaveGroup
  • onUserAfterSaveGroup
  • onUserBeforeDeleteGroup
  • onUserAfterDeleteGroup

Тип «Contact Component»

Плагины, которые выполняются в ходе работы с компонентом контактов.

Триггеры:

  • onValidateContact
  • onSubmitContact

Тип «Installer Component»

Плагины, которые выполняются в процессе работы инсталлера Joomla (установка и удаление расширений).

Триггеры:

  • onInstallerBeforeInstallation
  • onInstallerBeforeInstaller
  • onInstallerAfterInstaller

Тип «Menu Component»

Плагины, которые выполняются в ходе работы с пунктами меню Joomla.

Триггеры:

  • onAfterGetMenuTypeOptions

Тип «Module»

Плагины, которые выполняются в ходе работы с модулями.

Триггеры:

  • onRenderModule
  • onAfterRenderModule
  • onPrepareModuleList
  • onAfterModuleList
  • onAfterCleanModuleList

Как можно заметить, триггеры покрывают значительную часть функционала Joomla. Если вам нужно внедрить в каком-то месте свой собственный код, то с высокой долей вероятности вы сможете подобрать подходящий триггер.

Параметры триггеров в Joomla

Согласитесь, триггеры были бы не слишком полезны, если бы просто вызывали плагин, без какого-либо взаимодействия с остальным кодом. Например, какой смысл в триггере onUserLogin, вызывающемся после авторизации пользователя, если мы не знаем, какой именно пользователь был авторизован?

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

Подробное описание каждого из триггеров, а также список всех параметров, которые триггер передает в плагин, вы можете найти в документации по Joomla на этой странице.

Создание собственных триггеров

У вас может возникнуть вопрос: «Что делать, если ни один из существующих триггеров мне не подходит»? Бывают задачи, когда ваш код должен быть выполнен в таком месте, где триггеров нет. В этом случае вам придется сделать хак. Но это может быть либо большой хак, изменяющий блоки кода в разных местах файла, либо маленький, добавляющий ваш собственный триггер в нужное место.

Да, в Joomla вы можете создавать и собственные триггеры, а затем плагины уникальных типов для  них. Это может быть удобно с точки зрения минимизации изменений в хаке, либо тогда, когда вы пишите собственное расширение, и хотите дать сторонним разработчикам возможность делать для него плагины.

Создать собственный триггер в Joomla очень просто. Достаточно добавить в нужном вам месте следующий код:

JPluginHelper::importPlugin('<Тип_плагина>');
$dispatcher = JDispatcher::getInstance();
$results = $dispatcher->trigger( '<Название_триггера>',<Массив_параметров_триггера> );

Даже если вы сделали хак, восстановить три строчки кода гораздо проще, чем целые блоки.

Создание собственного плагина Joomla

Создать собственный плагин Joomla проще, чем может показаться на первый взгляд. Помните, что плагин, это не сложное расширение, а всего лишь кусок кода, который выполнится в нужном месте (хотя иногда встречаются действительно сложные плагины). Вот всё, что вам нужно, чтобы создать ваш собственный плагин: взять заголовку, изменить название, автора и прочую мета-информацию, и добавить в заготовку код, который должен выполняться при вызове тем или иным триггером.

Если вы хоть немного разбираетесь в PHP, и хотите написать собственный плагин, ознакомьтесь с этими материалами:

  • https://docs.joomla.org/Jx:Creating_a_Plugin_for_Joomla – инструкция по созданию собственного плагина на сайте документации Joomla (англ.)
  • https://github.com/joomla/joomla-cms-examples/tree/master/plugins – заголовки плагинов различных типов. Они немного устаревшие, но большинство работает в Joomla 3

Примеры использования плагинов Joomla

Напоследок, хочу привести несколько примеров того, что можно делать с помощью собственных плагинов.

  • Отправка письма пользователю после его авторизации, аналогично тому, как это сделано в ВК. Что-то вроде: «В ваш аккаунт выполнен вход…»
  • Автоматический репост анонса статьи в социальные сети после ее создания и сохранения в админке.
  • Автоматический сбор информации по всем запросам, которые вводили пользователи в форме поиска на сайте.
  • LazyLoad – «ленивая» подгрузка изображений в статье.
  • Добавление кнопок с уникальным функционалом в текстовом редакторе статьи.
  • Подмена мета-данных страниц сайта, избавление от дублей, перенаправление по определенным условиям.
  • Защита форм авторизации от подбора пароля

Всё это и многое другое можно реализовать с помощью плагинов Joomla, не используя хаки и не боясь, что изменения будут стерты при обновлении CMS.

На этом всё. Надеюсь, тема плагинов в Joomla стала для вас хотя бы чуточку понятнее. Если вам нужен какой-то нестандартный плагин, но вы не уверены, что сможете создать его самостоятельно, то всегда можете заказать у меня разработку.

———

Если вы серьезно занимаетесь IT-технологиями и ищите подходящий дата-центр для размещения своих серверов, то всегда можете разместить сервер в Москве. Здесь же можно арендавать сервер или серверную стойку. Поверьте, это гораздо удобнее, чем сидеть рядом с ним в офисе =).

Об авторе

Об авторе

Wedal (Виталий). Веб-разработчик полного цикла (Full Stack). Создатель и автор сайта Wedal.ru.

Основной профиль – создание сайтов и расширений на CMS Joomla.

  • Об авторе
  • Портфолио
  • Услуги
  • Контакты

Создание произвольного плагина

Вызов системных событий, собственная группа плагинов

рейтинг: 7.3/10, голосов: 23

  •  
  •  

Плагины можно применять не только для обработки системных событий, но и просто для расширения функционала собственного компонента — что-то вроде расширений к расширениям.

Эта статья поможет вам лучше понять, что необходимо сделать чтобы получить собственный плагин. Большинство из них состоят только из одного файла, который несет в себе сам код. Но для правильной установки и работы необходимо добавить еще XML-файл, который будет описывать процесс установки, мета данные и параметры.

Создание установочного файла

Как и для любых других расширений Joomla, установочный файл — это архив *.zip или *.tar.gz. В любом случае в архиве должен быть валидный XML, иначе установка будет не возможна. Ниже можно увидеть пример этого файла для поискового плагина

<?xml version="1.0" encoding="iso-8859-1"?>
<install version="1.5" type="plugin" method="upgrade" group="search">
    <name>Categories searchbot</name>
    <author>Joomla! Project</author>
    <creationDate>November 2005</creationDate>
    <copyright>(C) 2005 Open Source Matters. All rights reserved.</copyright>
    <license>GNU/GPL</license>
    <authorEmail>admin@joomla.org</authorEmail>
    <authorUrl>www.joomla.org</authorUrl>
    <version>1.1</version>
    <description>Allows searching of Categories information</description>
    
    <files>
        <filename plugin="categories.searchbot">categories.searchbot.php</filename>
    </files>
    
    <params>
        <param name="search_limit" type="text" size="5" default="50" label="Search Limit" description="Number of search items to return"/>        
    </params>
</install>

К важным моментам тут относятся

  • group=»search»
    Группа к которой принадлежит плагин. Она совпадает с названием директории, где будет располагаться файл. Например для поисковых плагинов будет использовать «<siteroot>/plugins/search».
  • <files><filename></filename></files>
    Список файлов, которые будут скопированы при установке.
  • <params>
    Параметры, который будут доступны при настройке плагина.
  • method=»upgrade»
    Параметр в теге <install> явно указывает что при установке не нужно удалять старые файлы, а только переписать их новыми из архива.

Остальные свойства очевидны.

Стоит заметить, что  ваш плагин должен содержать только уникальные функции и классы, чтобы избежать конфликтов с другими частями системы.

Если ваш плагин не использует функционал из существующих категорий, то укажите собственную группу. Во избежание ошибок, перед установкой, создайте необходимую категорию, например так

<siteroot>/plugins/mypugins

Исполняемый код

Joomla использует для реализации паттерн Наблюдатель (Observer). Лучше придерживаться именно такой реализации.

// запрет прямого доступа
defined( '_JEXEC' ) or die( 'Restricted access' );

// Импортируем зависимую библиотеку
jimport('joomla.plugin.plugin');

class plg<PluginGroup><PluginName> extends JPlugin
{
    /**
     * Конструктор класса
     */
    function plg<PluginGroup><PluginName>( &$subject )
    {
        // обязательно необходимо вызвать родительский конструктор
        parent::__construct( $subject );

        // загрузка параметров плагина
        $this->_plugin = JPluginHelper::getPlugin( '<GroupName>', '<PluginName>' );
        $this->_params = new JParameter( $this->_plugin->params );
    }
    
    /**
     * Методы плагина - это события, которые будут вызываться автоматически.
     */
    function <EventName>()
    {
        // Код плагина
        return true;
    }
}

Используем плагин в своем коде

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

Произвольный вызов события плагинов выглядит следующим образом

JPluginHelper::importPlugin('<PluginGroup>');
$dispatcher =& JDispatcher::getInstance();
$results = $dispatcher->trigger( '<EventName>', <ParameterArray> );

Массив параметров отправлять не обязательно. После выполнения этого кода, все активные плагины выбираются из общего списка, выстраиваются в порядке приоритета (он выбирается в панели управления, Менеджер плагинов, столбец «порядок») и в каждом из них вызывается метод имя которого совпадает с названием события. Метод в виде аргументов получит массив <ParameterArray>, каждый элемент которого будет новым аргументом.

grigoriev

9574

joomla создание плагина

DOWNLOAD

Недавно под задачу написал плагин для joomla и после этого решил сделать заметку о том как для joomla создать плагин.

Как работает джумла плагин

Для начала немного теории. Так что же такое плагин в контексте джумлы. А это скрипт, который исполняется в определённых местах основного цикла joomla.
Места выполнения скрипта ещё называют событиями. Работу плагина можно разбить на несколько шагов:

  • Все плагины, которые включены в админ панели включаются в цикл джумла.
  • Происходит вызов определённого события. Например в стандартном шаблоне для статьи компонента com_content
    встречается код echo $this->item->event->beforeDisplayContent. Это и есть вызов события.
  • Джумла выбирает из включенных плагинов те которые относятся к вызову события (плагины подразделяются на системные, контент, пользовательские и тд) и
    выполняет код метода вызываемого события (у нас это beforeDisplayContent ).

Пока не совсем всё ясно но к концу статьи должно проясниться. Ниже в таблице показаны какие события могут обрабатывать плагины joomla.

События плагинов joomla

Тип плагина Название события Описание
Аутентификация
(Authentication)
onUserAuthenticate Это событие срабатывает когда кто то авторизуется в админке или на сайте
Капча(Captcha) onInit
onDisplay

onCheckAnswer
События капчи
Контент (Content) onContentAfterDelete
onContentAfterDisplay
onContentAfterSave
onContentAfterTitle
onContentBeforeDelete
onContentBeforeDisplay
onContentBeforeSave
onContentBeforeTitle
onContentChangeState
onContentPrepare
onContentPrepareData
onContentPrepareForm
События контента (добавление, отображение, подготовка и тд )
Контакты (Contacts) onSubmitContact
onValidateContact
События обработки контактов (отправка контактов и валидация)
Редакторы (Editors) onInit
onSave
onSetContent
onGetContent
onGetInsertMethod
onDisplay
События редакторов joomla
Editors-XTD onDisplay
onCustomEditorButton
События специальных кнопок для редакторов (разрыв страницы и тд)
Расширение(Extension) onExtensionBeforeInstall
onExtensionBeforeUpdate
onExtensionBeforeUninstall
onExtensionAfterInstall
onExtensionAfterUpdate
onExtensionAfterUninstall
События расширений (установка модулей, компонентов и тд, удаление, обновление)
Система (System) onAfterInitialise
onAfterRoute
onAfterDispatch
onAfterRender
onBeforeCompileHead
onBeforeRender
Системные плагины выводятся после каждого цикла joomla
Пользователь (User) onUserAfterDelete
onUserBeforeDelete
onUserBeforeSave
onUserAfterSavev
onUserLogin
onUserLogout
onLoginFailure
onLogoutFailure
onUserAuthenticate
onUserAuthorisation
Эти события срабатывают при авторизации пользователя или редактировании его данных

Почти все плагины joomla являются классами. Они наследуются от класса JPlugin. Есть определённое соглашение о именовании плагина. Класс
плагина должен именоваться по такому типу: plgТип нашего плагинаНазвание нашего плагина
Тоесть если мы захотим создать контент плагин с названием hello название класса будет plgContentHello. Теперь мы обладаем всеми данными для написания плагина.

Манифест плагина

Я решил написать простой контент плагин, который выводит заданное в админ панели приветствие ( например «Здравствуйте уважаемые читатели блога») перед статьёй во всех статьях блога. Пользы от него конечно мало
но для примера написания плагина я думаю пойдёт. И так приступим. Плагин назовём Greet. Для начала создадим папку greet, а в ней файлы: index.html — это заглушка,
greet.xml — это файл манифест (для установки плагина), greet.php — файл с кодом самого плагина. В текстовом редакторе откроем greet.xml.
Ниже увидите листинг самого greet.xml

                                     
<?xml version="1.0" encoding="utf-8"?>
<extension version="3.5.0" type="plugin" group="content" method="upgrade">
  <name>PLG_CONTENT_GREET</name>
  <author>Aleksey Grigoriev</author>
  <creationDate>January 2017</creationDate>
  <copyright>Copyright (C) 2017>
  <license>GNU General Public License</license>
  <authorUrl>www.aweb34.ru</authorUrl>
  <version>3.0.0</version>
  <description>PLG_CONTENT_GREET_DESCRIPTION</description>
  <files>
    <filename plugin="greet">greet.php</filename>
    <filename>index.html</filename>
        <folder>language</folder>
  </files>
        <config>
            <fields name="params">
                <fieldset name="basic">
                    <field name="greet" type="text"
                        description="PLG_CONTENT_GREET_DESC"
                        label="PLG_CONTENT_GREET_LABEL"
                        filter="string"
                        default=""
                        size="30"
                    />
                </fieldset>
            </fields>
        </config>  
</extension>

Давайте разберёмся что здесь и к чему.

Тип расширения plugin, относится к группе content

<extension version="3.5.0" type="plugin" group="content" method="upgrade">

В папке находятся файл плагина и заглушка index.php, а так же папка с языковыми файлами, но об этом позже

 
<files>
    <filename plugin="greet">greet.php</filename>
    <filename>index.html</filename>
    <folder>language</folder>
</files>

В админ панели в настройках плагина будет тестовое поле с именем greet по умолчанию пустое с длинной в 30 символов.
В это поле мы будем вводить наше приветствие. Элемент fields с атрибутом name=»params» специально создан что бы мы могли получить параметры плагина.

<config>
    <fields name="params">
        <fieldset name="basic">
            <field name="greet" type="text"
                description="PLG_CONTENT_GREET_DESC"
                label="PLG_CONTENT_GREET_LABEL"
                filter="string"
                default=""
                size="30"
            />
        </fieldset>
    </fields>
</config>

Остальные поля я думаю интуитивно понятны.

Русификация плагина Joomla

Согласно манифесту у нас должна быть в папке greet папка с языковыми файлами. Так давайте создадим папку language в папке greet. Так же в папке language
создадим папку ru-RU, а в ней файлы ru-RU.plg_content_greet.ini и ru-RU.plg_content_greet.sys.ini. Обратите внимание, что в наименовании языковых файлов есть
определённые правила.
Так как плагин тестовый, английской локализации я не предусмотрел.
файл ru-RU.plg_content_greet.ini является основным языковым файлом. В нём находятся языковые константы, которые отвечают за отображение названий полей и тд, находящихся
внутри плагина, и за название плагина в менеджере плагинов. Листинг файла:

PLG_CONTENT_GREET_DESC="Введите в поле текст приветствия"
PLG_CONTENT_GREET_LABEL="Текст приветствия"    

Файл ru-RU.plg_content_greet.sys.ini отвечает за отображение языковых констант во время установки плагина. Листинг:

PLG_CONTENT_GREET="Плагин приветствия"
PLG_CONTENT_GREET_DESCRIPTION="Плагин выводит приветствие 
после заголовка статьи" 

Разработка плагина joomla

Как я писал выше, основной код плагина у нас находится в файле greet.php. Давайте откроем его в текстовом редакторе и вставим код из листинга ниже.

                                     
<?php
//запрещает доступ не из joomla
defined('_JEXEC') or die;
//создаём класс плагина 
class plgContentGreet extends JPlugin
{  
    //задаём тип события
    public function onContentBeforeDisplay( $context, &$row, &$params, $page = 0 )
    {
        //получаем значение поля приветствия
            $param = $this->params->get('greet', 'defaultValue');
        //выводим приветствие
            return $param;       
    }
}  

Тут я думаю всё просто. Назвали класс нашего плагина согласно договорённость plgContentGreet. Получили значение поля приветствия. Имя поля greet. Используя
метод onContentBeforeDisplay вывели наше приветствие.

Важно: Обратите внимание что приветствие мы вывели не через echo, а через return

Теперь нам осталось только запаковать папку greet в zip архив и установить наш плагин через менеджер расширений joomla. Скачать плагин можно
нажав на кнопку download в начале статьи.

Понравилась статья? Поделить с друзьями:
  • Как написать свой парсер на python
  • Как написать свой ориджинал
  • Как написать свой социальный портрет
  • Как написать свой обменник криптовалют
  • Как написать свой сниффер