Створення плагіна для 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 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.