Плагины

Основная цель

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

  • использование хуков и фильтров для расширения и изменения логики работы проекта
  • создание и подключение php шаблонов, файлов js/css/изображений
  • добавление/подмена шаблонов писем, SEO шаблонов, роутов, cron-задач
  • дополнение/перегрузка любого класса модуля (модели или компонента), а также классов ядра
  • модификация файлов модулей при помощи специальных инструкций  

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

Для того чтобы создать каркас плагина вам необходимо:

  • Авторизоваться в панели управления
  • Перейти в режим разработчика (в правом верхнем меню пользователя)
  • Перейти в раздел "Дополнения / Плагины" и нажать на ссылку "создать плагин" в правом верхнем углу
  • Указать название вашего нового плагина, например "Мой плагин"
  • Указать название плагина латиницей, например "example" (допустимые символы a-z, 0-9, _)
  • Нажать "Создать" (Create)
  • После чего система создаст директорию плагина /plugins/example/, а также файл index.php в ней
  • Созданный вами плагин отобразится в панели управления в разделе "Дополнения / Плагины".

Включаем плагин

Каждый плагин, для его работы в проекте, должен быть включен.

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

Структура плагина

Плагины располагаются в директории /plugins/. В директории плагина минимально обязательно наличие файла index.php. Рассмотрим пример его содержания на примере вновь созданного плагина под названием 'example':

<?php

class Plugin_Example extends Plugin
{
    public function init()
    {
        parent::init();

        $this->setSettings(array(
            'plugin_title'   => 'Название плагина',
            'plugin_version' => '1.0.0',
            'extension_id'   => '1234567890123456789012345678901234567890', // уникальный идентификатор дополнения
        ));

        $this->configSettings(array(
            // ...
        ));
        
        $this->blockAdd('block_key', function ($context){
            // ... 
        });
    }

    protected function start()
    {
        // код плагина, объявление хуков ...
    }
}

Опишем подробнее:

  • Название класса плагина всегда начинается с префикса Plugin_, а сам класс наследует базовый класс Plugin.
  • В обязательной функции init указывается название плагина, его версия и объявляются настройки. Также могут объявляться блоки.
  • Весь остальной код плагина следует размещать уже в функции start, а также в функциях данного класса. Дополнительные php файлы также подключайте в функции start, либо же непосредственно перед использованием.

Пример подключения других php файлов находящихся в директории плагина:

require $this->path('file.php');
require $this->path('dir/file.php');

Файлы статики

Плагин может иметь собственные файлы js, css, изображения, располагать которые следует в директории /static/ в директории плагина. В момент установки/включения плагина они будут скопированы в директорию: /public_html/plugins/название_плагина/

Пример подключения js / css файлов в рамках кода плагина:

$this->js('file.js');
$this->css('file.css');

Они будут иметь следующий полный путь:

/public_html/plugins/название_плагина/file.js
/public_html/plugins/название_плагина/file.css

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

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

Настройки плагина

Настройки плагина объявляются в методе init, подробнее о том как это сделать описано в данной статье.

Блоки

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

События

Для каждого из описанных событий работы плагина предусмотрена соответствующая функция:

  • install - установка
  • uninstall - удаление
  • enable - включение
  • disable - выключение
  • update - обновление

При необходимости выполнения дополнительных действий её можно расширить следующим образом:

protected function install()
{
    if ( ! parent::install()) return false;
    // дополнительные действия
    return true;
}
  • в примере показано расширение функции установки плагина
  • в первую очередь вызывается базовая функция и выполняется возврат в случае если результат ее работы отрицательный
  • далее вместо комментария можно добавить собственный код, например в случае если необходимо выполнить запуск sql файла доступен метод installSqlFile, рекомендуемый способ это миграции базы данных
  • в конечном итоге функция должна возвращать true - при успешном выполнении действий или же false - при наличии ошибок возникших в процессе.
  • идентичные правила действуют и для остальных упомянутых функций

Роутинг

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

Для примера добавим роут дающий возможность обращаться ко всем публичным методам плагина, для этого добавьте следующий код в методе start вашего плагина:

$this->routeAdd('plugin1/routes', array(
    'pattern' => 'plugin1/(.*)',
    'callback' => $this->routeAction('$1')
));

После чего при вызове следующего javascript кода будет выполнен AJAX запрос и обращение к публичному методу вашего плагина под названием test:

bff.ajax('/plugin1/test', {}, function(response){
    /* обработка ответа */
});

Код этого метода плагина для примера может быть следующим:

public function test()
{
     $response = array();
     // произвольный код
     $this->ajaxResponse($response);
}

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

Админ-панель

Для определения контекста запроса к админ-панели следует использовать метод bff::adminPanel()

protected function start()
{
    if (bff::adminPanel())
    {
        // подключение css/js файлов для админ-панели
        $this->cssAdmin('css/admin.css');
        $this->jsAdmin('js/admin.js');
    } else {
        // подключение css/js файлов для фронтенда
        $this->css('css/frontend.css');
        $this->js('js/frontend.js');
    }
}

Модули

Плагин имеет некоторые схожие с модулем возможности, а именно:

  • cronSettings - объявление запуска крон задач плагина
  • sendmailTemplates - объявление шаблонов писем плагина
  • seoTemplates - объявление SEO шаблонов плагина

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

Также плагин может содержать в себе целый модуль или же несколько модулей, аналогичных по структуре с теми что расположены в директории проекта /modules/ и зарегистрировать их следующим примером кода в функции плагина start:

bff::i()->moduleRegister('название модуля', $this->path('module_dir'));

Где 'module_dir' - название директории модуля в директории плагина, а 'название модуля' - название модуля указанное при создании латиницей. После этого в момент старта плагина (вызова функции start) будет выполнена регистрация данного модуля в системе и он начнет работать как обычный модуль из директории /modules/.

Создание каркаса модуля также доступно посредством консольной команды, пример и описание которой вы найдете здесь.

Локализация интерфейса

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

<?= $this->lang('Фраза требующая перевода'); ?>

Данные фразы будут доступны для перевода в настройках плагина в разделе "Локализация". Файлы перевода хранятся по следующему пути /plugins/название плагина/lang/{xx}.php и имеют следующую структуру:

<?php 
return array (
  'Исходная фраза1' => 'Перевод1',
  'Исходная фраза2' => 'Перевод2',
);

В момент сохранения перевода пользователем (в настройках дополнения) файлы перевода сохраняются в директории /files/extensions/название плагина/lang/{xx}.php Макрос {xx} означает двухбуквенный код языка, узнать требуемый код можно в файле /bff/languages.php.

Файл инструкции readme.md

В настройках плагина есть возможность включить раздел "Инструкция" с описанием порядка его установки и настройки. Для этого необходимо в корень директории плагина добавить файл readme.md. Файл поддерживает разметку Markdown, это означает что текст в нем можно отформатировать используя специальные конструкции, выделив необходимое жирным/курсивом, а также вставить ссылки и изображения. Также есть возможность локализации данного файла, например для формирования английской его версии его следует назвать readme-en.md, где можно заметить ключ языка en.

Данный файл также поддерживает некоторые макросы:
{plugin:title} - название плагина
{plugin:url} - URL путь к директории файлов статики плагина
{plugin:path} - относительный путь к директории плагина в проекте (включительно)
{theme}текст{/theme} - текст будет отображаться в случае если в проекте активирована тема,
также внутри этого блока доступны следующие макросы:
{theme:title} - название текущей темы
{theme:url} - URL путь к директории файлов статики темы
{theme:path} - относительный путь к директории темы в проекте (включительно)

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

Имеется исходный файл: /modules/bbs/tpl/def/item.view.owner.php
В подключенной теме theme1 есть аналогичный файл но уже с измененным содержимым: /themes/theme1/modules/bbs/tpl/def/item.view.owner.php
Модификатор плагина "цепляется" за некоторую строку которая в версии файла темы отсутствует, например должен выводит дополнительный блок на странице, но этого не происходит. Напишем в файле readme.md инструкцию которая будет отображаться только в случае неудачного применения модификатора (некорректной его работы), для этого обрамим текст данной части описания следующим кодом:

{theme:file:/modules/bbs/tpl/def/item.view.owner.php}
Описание того что требуется сделать пользователю с версией этого файла в теме. Например:
Добавьте в файл шаблона **{theme:file:path}** следующий код:
`<?php echo $code; ?>`
Рекомендуемое расположение - сразу после строки: `<div class="v-author__contact_write">`
{/theme:file}

Кроме макросов {theme:file:путь к файлу} и {/theme:file} также можно увидеть контекстный макрос {theme:file:path} выполняющий подстановку пути к файлу о котором идет речь.

Миграции

Плагин может вносить изменения в структуру базы данных как дополняя стуктуру существующих таблиц в проекте так и создавая новые таблицы. Подробнее о работе с миграциями читайте в статье "База данных / Миграции"

Ошибки

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