Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Первый плагин

Событие — момент в работе Joomla, о котором она сообщает всем желающим: «текст статьи готовится к выводу», «пользователь вошёл», «запись сохранена». Плагин — класс, который подписан на такие события и выполняет свой код, когда они происходят. Напишем плагин, который заменяет в статьях метку {year} текущим годом.

Где лежит

Плагины разложены по группам. Группа — это папка внутри plugins; плагин группы content обрабатывает события содержимого. Создайте вручную:

plugins/content/hello/
├── hello.xml                    манифест
├── services/
│   └── provider.php             подключение плагина
└── src/
    └── Extension/
        └── Hello.php            класс плагина

Полное имя такого плагина — plg_content_hello.

Манифест

<?xml version="1.0" encoding="UTF-8"?>
<!-- plugins/content/hello/hello.xml -->
<extension type="plugin" group="content" method="upgrade">
    <name>plg_content_hello</name>
    <version>1.0.0</version>
    <description>Подставляет текущий год в текст статей</description>
    <namespace path="src">My\Plugin\Content\Hello</namespace>
 
    <files>
        <folder plugin="hello">services</folder>
        <folder>src</folder>
    </files>
</extension>

От манифеста модуля он отличается типом plugin, атрибутом group и атрибутом plugin="hello" у первой папки.

Провайдер

// plugins/content/hello/services/provider.php
defined('_JEXEC') or die;
 
use Joomla\CMS\Extension\PluginInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\DI\Container;
use Joomla\DI\ServiceProviderInterface;
use Joomla\Event\DispatcherInterface;
use My\Plugin\Content\Hello\Extension\Hello;
 
return new class () implements ServiceProviderInterface {
    public function register(Container $container): void
    {
        $container->set(
            PluginInterface::class,
            function (Container $container) {
                $plugin = new Hello(
                    $container->get(DispatcherInterface::class),
                    (array) PluginHelper::getPlugin('content', 'hello'),
                );
                $plugin->setApplication(Factory::getApplication());
 
                return $plugin;
            },
        );
    }
};

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

Класс плагина

// plugins/content/hello/src/Extension/Hello.php
namespace My\Plugin\Content\Hello\Extension;
 
defined('_JEXEC') or die;
 
use Joomla\CMS\Event\Content\ContentPrepareEvent;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
 
final class Hello extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            'onContentPrepare' => 'replaceYear',
        ];
    }
 
    public function replaceYear(ContentPrepareEvent $event): void
    {
        $article = $event->getItem();
 
        if (empty($article->text)) {
            return;
        }
 
        $article->text = str_replace('{year}', date('Y'), $article->text);
    }
}

Интерфейс SubscriberInterface требует метод getSubscribedEvents(): он возвращает пары «событие → метод». Событие onContentPrepare происходит перед выводом текста; обработчик получает объект события, достаёт из него статью и меняет её текст.

Класс ContentPrepareEvent появился в Joomla 5. В Joomla 4 обработчик получает общий объект Joomla\Event\Event, а статья лежит в его аргументах.

Установка и результат

  1. «Система → Установка → Поиск» → установите plg_content_hello.
  2. «Система → Плагины» → найдите плагин и включите его: после установки плагины выключены.
  3. Допишите в текст статьи строку © {year} Анна Иванова и откройте статью на сайте.

Вместо метки выведен текущий год.

Параметры плагина

Настройки описывают в манифесте так же, как у модуля:

<config>
    <fields name="params">
        <fieldset name="basic">
            <field name="marker" type="text" label="Метка для замены" default="{year}" />
        </fieldset>
    </fields>
</config>

В классе плагина они доступны в свойстве $this->params:

$marker = $this->params->get('marker', '{year}');
 
$article->text = str_replace($marker, date('Y'), $article->text);

Поле «Метка для замены» появится в форме плагина в разделе «Система → Плагины».

Частая ошибка

Событие onContentPrepare вызывается не только для статей, но и для модулей, описаний категорий и других текстов — много раз на одной странице. Медленный код в обработчике замедлит весь сайт. Проверяйте контекст — $event->getContext() === 'com_content.article' — и выходите из метода сразу, если текст вам не подходит.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.