Как расширять плагины в OctoberCMS

Научимся расширять сторонние плагины в OctoberCMS: контроллеры, модели, импорт и экспорт

Все действия осуществляются в boot() своего plugin.php.

Шаг 1. Подготовка

Для начала необходимо создать плагин, назовём его Extender.

php artisan create:plugin Site21.Extender

и подключить контроллеры и модели плагинов которые Вы хотите расширить.

За пример возьмем плагин Rainlab.User. У него есть все что нам нужно расширить: модели, котроллеры, импорт и экспорт.

use RainLab\Blog\Controllers\Posts;
use RainLab\Blog\Models\Post;

Теперь к контроллеру мы можем обращаться через Posts, а к модели через Post.

Шаг 2. Расширяем БД

Наши данные где-то должны храниться, поэтому мы должны расширить БД через миграциию. Можем это сделать:

  • если создадим свою таблицу (например для тегов или серий, чтобы они хранились в отдельной таблице и управлять ими через отдельный контроллер)
  • расширить существуюущую таблицу постов добавив в нее новые колонки

В этом уроке мы научимся обоим вариантам.

Вариант 1. С помощью своей таблицы

Для первого варианта нам нужна будет своя модель (к примеру для тегов). Создадим её и назовём Tag. Также мы хотим управлять нашими тегами через админку, поэтому сразу создадим свой контроллер Tags

php artisan create:model Site21.Extender Tag
php artisan create:controller Site21.Extender Tags

Теперь в нашу новую таблицу необходимо добавить некоторые поля. После создания модели у нас создался новый файл create_tags_table.php в папке updates плагина. Добавим туда колонки name и description для примера. Файл получится таким:

<?php namespace Site21\Extender\Updates;

use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;

class CreateTagsTable extends Migration
{
    public function up()
    {
        Schema::create('site21_extender_tags', function (Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->string('name');
            $table->text('description')->nullable();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('site21_extender_tags');
    }
}

В этом варианте предполагается что мы не будем затрагивать таблицу rainlab_blog_posts, поэтому создадим еще одну новую таблицу в БД для линковки постов и тегов. Создадим новый файл с миграцией в папке updates create_tags_posts_table.php с содержимым:

<?php namespace Site21\Extender\Updates;

use Schema;
use October\Rain\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;

class CreateTagsPostsTable extends Migration
{
    public function up()
    {
        Schema::create('site21_extender_tags_posts', function (Blueprint $table) {
            $table->engine = 'InnoDB';
            $table->increments('id');
            $table->integer('tag_id');
            $table->integer('post_id');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('site21_extender_tags_posts');
    }
}

В этой же папке updates есть файл version.yaml, дописываем туда наши новые миграции:

1.0.1: First version of Extender
1.0.2: 
  - Create tags table
  - create_tags_table.php
1.0.3: 
  - Create tags posts table
  - create_tags_posts_table.php

и запускаем:

php artisan october:up

Закончим создание контроллера добавлением в подменю Блог новой ссылки Теги для удобства управления. Для этого в boot() пишем:

// добавляем ссылку тегов в контекст блога
\Event::listen('backend.menu.extendItems', function($manager) {
    $manager->addSideMenuItems('RainLab.Blog', 'blog', [
        'tags' => [
            'code'  => 'tags',
            'label' => 'Теги',
            'icon'  => 'icon-tags',
            'url'   => Backend::url('site21/extender/tags'),
            'order' => 550,
        ],
    ]);
});

Пункт меня добавился в подменю блога, но для того чтобы показать контроллеру Tags его новое место редактируем его и заменяем строчку BackendMenu::setContext на

BackendMenu::setContext('RainLab.Blog', 'blog', 'posts');

Напоследок оформляем в папке модели tag fields.yaml:

fields:
    id:
        label: ID
        disabled: true
        hidden: true

    name:
        label: Название
        type: text
        span: auto
        required: 1

    description:
        label: Описание
        type: textarea
        span: auto

и columns.yaml

columns:
    id:
        label: ID
        searchable: true
        width: 50px

    name:
        label: Название
        searchable: true

Теперь мы можем добавлять/редактировать и удалять теги. К постам подключим новое поле с выбором тегов на следующем шаге.

Вариант 2. С помощью добавления колонок в существующую таблицу

Для этого варианта нам не нужно создать ни контроллер, ни модель, расширим существующие от Блога. Но миграцию создать все равно нужно. Создадим файл add_column_to_post.php со следующим содержимым в папке updates:

<?php namespace Site21\Extender\Updates;

use Schema;
use Illuminate\Database\Schema\Blueprint;
use October\Rain\Database\Updates\Migration;


class AddColumnToPost extends Migration
{
    const TABLE_NAME = 'rainlab_blog_posts';
    
    public function up()
    {
        if (!Schema::hasTable(self::TABLE_NAME) || Schema::hasColumn(self::TABLE_NAME, 'featured')) {
            return;
        }

        Schema::table(self::TABLE_NAME, function (Blueprint $obTable)
        {
            $obTable->integer('featured')->default(0);
        });
    }

    public function down()
    {
        if (!Schema::hasTable(self::TABLE_NAME) || !Schema::hasColumn(self::TABLE_NAME, 'featured')) {
            return;
        }

        Schema::table(self::TABLE_NAME, function (Blueprint $obTable)
        {
            $obTable->dropColumn(['featured']);
        });
    }
}

Названите файла класса, таблицы может быть любым. Показываю поэтапность.

В данном примере мы добавили integer колонку в таблицу с постами. С помощью этой колонки будем отбирать избранные посты в дальнейшем. Подробнее о том как работать с БД через миграции описано в документации OctoberCMS.

Далее в version.yaml пишем о новой версии:

1.0.4: 
  - Add column featured to post
  - add_column_to_post.php

и запускаем:

php artisan october:up

Шаг 3. Расширяем контроллер и модель

Самое время добавить новые поля в админку. Добавим новую колонку featured с типом Switch и выбор тегов с типом . Обо всех типах формы написано в документации OctoberCMS.

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

Шаг 3. Расширяем контроллер и модель

В boot() пишем:

\Event::listen('backend.form.extendFields', function($widget) {
    if (!$widget->getController() instanceof Posts || $widget->isNested || $widget->alias != 'form') {
        return;
    }

    if (!$widget->model instanceof Post) {
        return;
    }

    // Добавляем необходимые колонки
    $widget->addSecondaryTabFields([
        'featured' => [
            'label' => 'Избранное',
            'type' => 'switch',
            'span' => 'auto'
        ],
        'tags' => [
            'label' => 'Теги',
            'type' => 'taglist',
            'mode' => 'relation',
            'span' => 'auto'
        ]
    ]);
});

// Расширяем модель добавив связь для первого варианта
Post::extend(function ($model) {
    $model->belongsToMany = array_merge(
        $model->belongsToMany,
        ['tags' => [
            'Site21\Extender\Models\Tag',
            'table' => 'site21_extender_tags_posts', 
            'key' => 'post_id', 
            'otherKey' => 'tag_id'
        ]]
    );
});

Отлично! Поля сохраняются, все хорошо.

Если не указана настрйока "tab", то всегда будет публиковаться во вкладку "Разное". Если Вы хотите разместить поле в существующую таблицу, то написать на русском "Управление" будет неверно, система создаст новую вкладку. Чтобы добавить поле в существующую вкладку Вам нужно перейти в fields.yaml необходимого модуля и посмотреть как назвается влкадка там. На примере блога это:

tab: 'rainlab.blog::lang.post.tab_edit'

Шаг 5. Расширяем импорт и экспорт

Для расширения импорт и экспорта у нас есть несколько шагов:

5.1 Добавить колонки в список импорта и экспорта

Действие расширяется через $controller->importExportConfig

Со вторым вариантом (поле featured) все просто:

// Расширяем импорт и экспорт необходимого контроллера
Posts::extend(function($controller) {
    // Получаем конфиг $importExportConfig у нашего контроллера
    $config = $controller->makeConfig($controller->importExportConfig);

    // Добавляем колонки в Экспорт
    $export = $controller->makeConfig($config->export['list']);
    $export->columns['featured'] = 'Избранное';

    // Добавляем колонки в Импорт
    $import = $controller->makeConfig($config->import['list']);
    $import->columns['featured'] = 'Избранное';
    
    // Переназначаем конфиг
    $config->export['list'] = $export;
    $config->import['list'] = $import;
    $controller->importExportConfig = (array) $config;
});

В случае если колонки импорта и экспорта уже указаны в importExportConfig, например как в Shopaholic, то добавлять еще проще (пример):

// Получаем конфиг $importExportConfig у нашего контроллера
$config = $controller->makeConfig($controller->importExportConfig);

// Добиваем колонку с фильтрами
$config->import['list']['columns']['filters'] = ['label' => 'Фильтры'];

// Переназначаем конфиг
$controller->importExportConfig = (array) $config;

Пишите dd($config) и смотрите как реализовано в расшряемом плагине.

5.2 Дописываем механизм импорта/экспорта

Для простых полей (2-ой вариант) уже все реализовано, но вот для тегов (1-ый вариант) еще нужно доработать чтобы при импорте создавалась новая запись в нужную таблицу.

Об этом мы поговорим в следующем уроке.


Опубликовано 15 июня 2021 г. в категориях: October CMS Winter CMS

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

Связаться со мной Fill 1