Создание плагина для PHP Composer'а

    При развертывании 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'а этот класс должен имплементировать интерфейс 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'а. Спасибо всем, кто дочитал до конца.
    Поделиться публикацией

    Похожие публикации

    Комментарии 0

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

    Самое читаемое