При развертывании Magento-приложений с использованием Magento Composer столкнулись с проблемой, что различные экземпляры одного и того же приложения (девелоперский, тестовый и т.д.) должны использовать различные локальные настройки (например, параметры подключения к БД). До этого, в другом проекте, использовался подход, когда в приложении (под контролем версий) находятся шаблоны конфигурационных файлов с placeholder'ами и скрипт, замещающий placeholder'ы локальными значениями и копирующий результат в нужное место. Локальные значения хранились отдельно для каждого экземпляра по месту развертывания. Хотелось привычный подход сохранить и для нового метода развертывания. Поиск устраивающего плагина на packagist.org завершился ненахождением, в силу чего и родилась идея сделать подобный плагин самостоятельно. При создании плагина пришлось надергать информацию из различных источников — информации с сайта Composer'а по плагинам оказалось недостаточно. Что и привело к написанию этой статьи.
Основной файл плагин-пакета выглядит примерно так:
Параметр 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'а этот класс должен имплементировать интерфейс Composer\Plugin\PluginInterface.
Конфигурация параметров работы плагина осуществляется через секцию extra в composer.json основного пакета, в котором используется наш плагин.
Плагин должен взять настройки для своей работы из файла, который задается через параметр extra.praxigento_templates_config конфигурационного файла проекта (composer.json). Мы это делаем при инициализации плагина:
В своей реализации плагина мы хотели, чтобы он реагировал на события:
Для этого наша точка входа должна также имплементировать интерфейс EventSubscriberInterface, подписаться на соответствующие события и зарегистрировать обработчки:
Подключение PhpUnit осуществляется в composer.json:
Настройки юнит-тестирования — в файле phpunit.xml.dist:
Загрузка autoloader'а, совместимого с PSR-4 (без него не запускаются тесты через IDE PhpStorm) в скрипте phpunit.bootstrap.php:
Запуск тестов через composer:
Данной информации должно хватить для создания собственного плагина для 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'а этот класс должен имплементировать интерфейс Composer\Plugin\PluginInterface.
namespace Praxigento\Composer\Plugin\Templates; use Composer\Composer; use Composer\IO\IOInterface; use Composer\Plugin\PluginInterface; 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'а. Спасибо всем, кто дочитал до конца.
