При развертывании Magento-приложений с использованием Magento Composer столкнулись с проблемой, что различные экземпляры одного и того же приложения (девелоперский, тестовый и т.д.) должны использовать различные локальные настройки (например, параметры подключения к БД). До этого, в другом проекте, использовался подход, когда в приложении (под контролем версий) находятся шаблоны конфигурационных файлов с placeholder'ами и скрипт, замещающий placeholder'ы локальными значениями и копирующий результат в нужное место. Локальные значения хранились отдельно для каждого экземпляра по месту развертывания. Хотелось привычный подход сохранить и для нового метода развертывания. Поиск устраивающего плагина на packagist.org/ завершился ненахождением, в силу чего и родилась идея сделать подобный плагин самостоятельно. При создании плагина пришлось надергать информацию из различных источников — информации с сайта Composer'а по плагинам оказалось недостаточно. Что и привело к написанию этой статьи.
composer.json
Основной файл плагин-пакета выглядит примерно так:
{
"name": "praxigento/composer_plugin_templates",
"type": "composer-plugin",
"require": {
"composer-plugin-api": "1.0.0"
},
"autoload": {
"psr-4": {
"\Praxigento\Composer\Plugin\Templates\": "src/"
}
},
"extra": {
"class": "\Praxigento\Composer\Plugin\Templates\"
},
"scripts": {
"test": "phpunit"
}
}
Параметр name заполняется по своему вкусу, у меня получился praxigento/composer_plugin_templates.
С параметрами type и require все достаточно однозначно — они должны быть и быть именно такими.
Параметр autoload.psr-4 определяет настройку автозагрузки классов плагина в соответствии с PSR-4 (рекомендуется использовать именно этот стандарт, т.к. PSR-0 устарел 21 октября 2014 года). Согласно этой настройки наши исходники располагаются в подкаталоге ./src/.
Параметр extra.class определяет основной класс плагина, который подгружается Composer'ом (или набор классов, если значение параметра — массив).
Параметр scripts.test позволяет запускать тестирование плагина из командной строки: "$ composer test".
Точка входа
Класс, заданный в extra.class, является точкой входа Composer'а в наш плагин. Согласно требованиям Composer'а этот класс должен имплементировать интерфейс ComposerPluginPluginInterface.
namespace PraxigentoComposerPluginTemplates;
use ComposerComposer;
use ComposerIOIOInterface;
use ComposerPluginPluginInterface;
class Main implements PluginInterface {
protected $composer;
protected $io;
public function activate(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
}
}
Доступ к параметрам
Конфигурация параметров работы плагина осуществляется через секцию extra в composer.json основного пакета, в котором используется наш плагин.
{
"name": "vendor/package",
"type": "project",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/praxigento/composer_plugin_templates"
}
],
"require": {
"praxigento/composer_plugin_templates": "*"
},
"extra": {
"praxigento_templates_config": "./instance_cfg.json"
}
}
Плагин должен взять настройки для своей работы из файла, который задается через параметр extra.praxigento_templates_config конфигурационного файла проекта (composer.json). Мы это делаем при инициализации плагина:
class Main implements PluginInterface, EventSubscriberInterface {
public function activate(Composer $composer, IOInterface $io) {
$this->composer = $composer;
$this->io = $io;
$extra = $composer->getPackage()->getExtra();
$configFile = $extra['praxigento_templates_config'];
}
}
Обработка событий
В своей реализации плагина мы хотели, чтобы он реагировал на события:
- post-install-cmd
- post-update-cmd
Для этого наша точка входа должна также имплементировать интерфейс EventSubscriberInterface, подписаться на соответствующие события и зарегистрировать обработчки:
class Main implements PluginInterface, EventSubscriberInterface {
public static function getSubscribedEvents() {
$result = array(
ScriptEvents::POST_INSTALL_CMD => array(
array( 'onPostInstallCmd', 0 )
),
ScriptEvents::POST_UPDATE_CMD => array(
array( 'onPostUpdateCmd', 0 )
),
);
return $result;
}
public function onPostInstallCmd(CommandEvent $event) {
}
public function onPostUpdateCmd(CommandEvent $event) {
}
}
Запуск тестов
Подключение PhpUnit осуществляется в composer.json:
{
"require-dev": {
"phpunit/phpunit": "4.4.*"
}
}
Настройки юнит-тестирования — в файле phpunit.xml.dist:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="phpunit.bootstrap.php"
>
<testsuites>
<testsuite name="Plugin Test Suite">
<directory suffix="_Test.php">./src/</directory>
</testsuite>
</testsuites>
</phpunit>
Загрузка autoloader'а, совместимого с PSR-4 (без него не запускаются тесты через IDE PhpStorm) в скрипте phpunit.bootstrap.php:
require __DIR__.'/vendor/autoload.php';
Запуск тестов через composer:
$ composer test
Заключение
Данной информации должно хватить для создания собственного плагина для Composer'а. Спасибо всем, кто дочитал до конца.
Автор: flancer