Плагины

Плагины должны предоставлять файл composer.json в корне плагина, чтобы быть распознанными Elgg.

elgg-plugin.php

elgg-plugin.php — это статический файл конфигурации плагина. Он читается Elgg для настройки различных сервисов и должен возвращать массив, если присутствует. Он не должен включаться плагинами и не гарантируется, что будет выполняться в какое-либо конкретное время. Кроме магических констант, таких как __DIR__, его возвращаемое значение не должно изменяться. В настоящее время поддерживаются следующие секции:

  • plugin — определяет информацию о плагине и зависимости

  • bootstrap — определяет класс, используемый для загрузки плагина

  • entities — определяет типы и классы сущностей и при желании регистрирует их для поиска

  • actions — устраняет необходимость вызова elgg_register_action()

  • routes — устраняет необходимость вызова elgg_register_route()

  • settings — устраняет необходимость установки значений по умолчанию при каждом вызове elgg_get_plugin_setting()

  • user_settings — устраняет необходимость установки значений по умолчанию при каждом вызове elgg_get_plugin_user_setting()

  • views — позволяет плагинам создавать псевдонимы для ресурсов поставщиков в путь в системе представлений Elgg

  • widgets — устраняет необходимость вызова elgg_register_widget_type()

  • events — устраняет необходимость вызова elgg_register_event_handler()

  • cli_commands — массив классов Elgg/Cli/Command для расширения функциональности elgg-cli

  • view_extensions — устраняет необходимость вызова elgg_extend_view() или elgg_unextend_view()

  • theme — массив переменных темы

  • group_tools — массив доступных опций групповых инструментов

  • view_options — массив представлений с дополнительными опциями

  • notifications — массив событий уведомлений

  • web_services — массив открытых веб-сервисов (используется плагином Web Services)

return [
        'plugin' => [
                'name' => 'Plugin Name', // readable plugin name
                'activate_on_install' => true, // only used on a fresh install
                'version' => '1.3.1', // version of the plugin
                'dependencies' => [
                        // optional list op plugin dependencies
                        'blog' => [],
                        'activity' => [
                                'position' => 'after',
                                'must_be_active' => false,
                        ],
                        'file' => [
                                'position' => 'before',
                                'version' => '>2', // composer notation of required version constraint
                        ],
                ],
        ],

        // Bootstrap must implement \Elgg\PluginBootstrapInterface
        'bootstrap' => MyPluginBootstrap::class,

        'entities' => [
                [
                        // Register a new object subtype and tell Elgg to use a specific class to instantiate it
                        'type' => 'object',
                        'subtype' => 'my_object_subtype',
                        'class' => MyObjectClass::class,

                        'capabilities' => [
                                // Register this subtype for search
                                'searchable' => true,

                                'likable' => true,
                        ],
                ],
        ],

        'actions' => [
                // Registers an action
                // By default, action is registered with 'logged_in' access
                // By default, Elgg will look for file in plugin's actions/ directory: actions/my_plugin/action.php
                'my_plugin/action/default' => [],

                'my_plugin/action/custom_access' => [
                        'access' => 'public', // supports 'public', 'logged_in', 'logged_out', 'admin'
                ],

                // you can use action controllers instead of action files by setting the controller parameters
                // controller must be a callable that receives \Elgg\Request as the first and only argument
                // in example below, MyActionController::__invoke(\Elgg\Request $request) will be called
                'my_plugin/action/controller' => [
                        'controller' => MyActionController::class,
                ],
        ],

        'routes' => [
                // routes can be associated with resource views or controllers
                'collection:object:my_object_subtype:all' => [
                        'path' => '/my_stuff/all',
                        'resource' => 'my_stuff/all', // view file is in resources/my_stuff/all
                ],

                // similar to actions, routes can be associated with a callable controller that receives an instance of \Elgg\Request
                'collection:object:my_object_subtype:json' => [
                        'path' => '/my_stuff/json',
                        'controller' => JsonDumpController::class,
                ],

                // route definitions support other parameters, such as 'middleware', 'requirements', 'defaults'
                // see elgg_register_route() for all options
        ],

        'widgets' => [
                // register a new widget
                // corresponds to a view in widgets/my_stuff/content
                'my_stuff' => [
                        'description' => elgg_echo('widgets:my_stuff'),
                        'context' => ['profile', 'dashboard'],
                ],
        ],

        'settings' => [
                'plugin_setting_name' => 'plugin_setting_value',
        ],

        'user_settings' => [
                'user_setting_name' => 'user_setting_value',
        ],

        'views' => [
                'default' => [
                        'cool_lib/' => __DIR__ . '/vendors/cool_lib/dist/',
                ],
        ],

        'events' => [
                'delete' => [
                        'object' => [
                                'file_handle_object_delete' => [
                                        'priority' => 999,
                                ],
                        ],
                ],
                'create' => [
                        'relationship' => [
                                '_elgg_send_friend_notification' => [],
                        ],
                ],
                'log' => [
                        'systemlog' => [
                                'Elgg\SystemLog\Logger::log' => ['unregister' => true],
                        ],
                ],
                'register' => [
                        'menu:owner_block' => [
                                'blog_owner_block_menu' => [
                                        'priority' => 700,
                                ],
                        ],
                ],
                'usersettings:save' => [
                        'user' => [
                                '_elgg_save_notification_user_settings' => ['unregister' => true],
                        ],
                ],
        ],

        'cli_commands' => [
                \My\Plugin\CliCommand::class,
                '\My\Plugin\OtherCliCommand',
        ],

        'view_extensions' => [
                'page/components/list' => [
                        'list/extension' => [
                                'priority' => 600,
                        ],
                ],
                'forms/usersettings/save' => [
                        'core/settings/account/password' => [
                                'unextend' => true,
                        ],
                ],
        ],

        'theme' => [
                'body-background-color' => '#000',
        ],

        'group_tools' => [
                'activity' => [], // just use default behaviour
                'blog' => [
                        'default_on' => false,
                ],
                'forum' => [
                        'unregister' => true, // unregisters the group tool option
                ],
        ],

        'view_options' => [
                'likes/popup' => [
                        'ajax' => true, // registers the view available via ajax
                ],
                'likes/popup' => [
                        'ajax' => false, // unregisters the view available via ajax
                ],
                'manifest.json' => [
                        'simplecache' => true, // register view as usable in the simplecache
                ],
        ],
        'notifications' => [
                'object' => [
                        'blog' => [
                                'publish' => [
                                        Elgg\Notifications\NotificationEventHandler::class => [], // registers the event to be notified
                                ],
                        ],
                        'thewire' => [
                                'create' => [
                                        Elgg\Notifications\NotificationEventHandler::class => [
                                                'unregister' => true, // unregisters the event to be notified
                                        ],
                                ],
                        ],
                        'page' => [
                                'create' => [
                                        MyPluginPageCreateEventHandler::class => [], // a custom event handler, needs to be an extension of a NotificationEventHandler
                                ],
                        ],
                ],
        ],
        'web_services' => [
                'test.echo' => [
                        'GET' => [ // the HTTP call method (GET|POST)
                                'callback' => 'my_echo', // required
                                'description' => 'A testing method which echos back a string', // optional, the description of the API method, a magic translation key is tried if not provided 'web_services:api_methods:<method>:<http call method>:description'
                                'params' => [ // optional, input parameters for the API method
                                        'string' => [
                                                'type' => 'string', // type of the parameter (int|integer|bool|string|float|array)
                                                'default' => 'some value', // default value if not provided in the request
                                                'required' => true|false, // required in the request
                                        ],
                                ],
                                'require_api_auth' => false, // optional, requires API authentication (default: false)
                                'require_user_auth' => false, // optional, requires User authentication (default: false)
                                'associative' => false, // optional, provide the input params as an array to the callback function (default: false)
                        ],
                ],
        ],
];

Класс загрузки

Начиная с Elgg 3.0 рекомендуемый способ загрузки вашего плагина — использовать класс загрузки. Этот класс должен реализовывать интерфейс \Elgg\PluginBootstrapInterface. Вы можете зарегистрировать ваш класс загрузки в elgg-plugin.php.

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

См.также

Для получения дополнительной информации о различных функциях, определённых в \Elgg\PluginBootstrapInterface, пожалуйста, прочитайте Загрузка плагина

elgg-services.php

Плагины могут прикреплять свои сервисы к публичному контейнеру внедрения зависимостей Elgg, предоставляя определения PHP-DI в elgg-services.php в корне директории плагина.

Этот файл должен возвращать массив определений PHP-DI. Сервисы будут доступны через elgg().

return [
   PluginService::class => \DI\object()->constructor(\DI\get(DependencyService::class)),
];

Затем плагины могут использовать PHP-DI API для автопривязки и вызова сервиса:

$service = elgg()->get(PluginService::class);

См. документацию по PHP-DI для получения полного списка возможностей определения и вызова.

composer.json

Поскольку Elgg поддерживает установку как зависимость Composer, поддержка Composer вашими плагинами упрощает установку администраторами сайтов. Чтобы сделать ваш плагин совместимым с Composer, вам необходимо как минимум иметь файл composer.json в корне вашего плагина.

Вот пример файла composer.json:

{
        "name": "company/example_plugin",
        "description": "Some description of the plugin",
        "type": "elgg-plugin",
        "keywords": ["elgg", "plugin"],
        "license": "GPL-2.0-only",
        "support": {
                "source": "URL to your code repository",
                "issues": "URL to your issue tracker"
        },
        "conflict": {
                "elgg/elgg": "<3.0"
        }
}

Подробнее о формате composer.json читайте на сайте Composer.

Важные части в файле composer.json:

  • name: имя вашего плагина, сохраняйте его в соответствии с именем папки вашего плагина для обеспечения правильной установки

  • type: это сообщит Composer, куда установить ваш плагин, ВСЕГДА сохраняйте это как elgg-plugin

В качестве рекомендации включите правило conflict с любой версией Elgg ниже вашей минимальной требуемой версии, это поможет предотвратить случайную установку вашего плагина на несовместимую версию Elgg.

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

Тесты

Рекомендуется создавать тесты PHPUnit для вашего плагина. Все тесты должны находиться в tests/phpunit/unit для модульных тестов и tests/phpunit/integration для интеграционных тестов.

Модульные тесты должны расширять класс Elgg\UnitTestCase. Интеграционные тесты должны расширять Elgg\Plugins\IntegrationTestCase.

Существует набор глобальных интеграционных тестов плагинов, которые выполняются на всех активных плагинах. Эти тесты:

  • Elgg\Plugins\ActionRegistrationIntegrationTest протестирует все зарегистрированные действия плагина без предоставления данных

  • Elgg\Plugins\ComposerIntegrationTest протестирует, считается ли composer.json действительным

  • Elgg\Plugins\StaticConfigIntegrationTest протестирует секции elgg-plugin.php и проверит правильный формат

  • Elgg\Plugins\TranslationsIntegrationTest протестирует все языковые файлы на правильный формат и кодировку

  • Elgg\Plugins\ViewStackIntegrationTest протестирует все представления плагина на наличие ошибок парсинга PHP