Настройка и использование плагинов
Описание
Вы можете изменить или расширить функциональность Composer, создав собственные плагины. Например, если ваша среда предъявляет особые требования к поведению Composer, которые не относятся к большинству пользователей, или если вы хотите использовать Composer каким-то образом, который нежелателен для большинства пользователей.
В этих случаях вы можете рассмотреть возможность создания плагина для обработки вашей специфической логики.
Создание плагина
Плагин — это обычный пакет Composer, который поставляет свой код как часть пакета и может также зависеть от других пакетов.
Пакет плагина
Файл пакета такой же, как и любой другой файл пакета, но с следующими требованиями:
- Атрибут type должен быть
composer-plugin. - Атрибут extra должен содержать элемент
class, определяющий имя класса плагина (включая пространство имён). Если пакет содержит несколько плагинов, это может быть массив имён классов. - Необходимо потребовать специальный пакет, называемый
composer-plugin-api, чтобы определить, с какими версиями API плагинов совместим ваш плагин. Требование этого пакета фактически не включает дополнительные зависимости, а только указывает, какую версию API плагина использовать.
Примечание: При разработке плагина, хотя это и не обязательно, полезно добавить зависимость require-dev от
composer/composer, чтобы иметь автодополнение в IDE для классов Composer.
Требуемая версия composer-plugin-api следует тем же правилам, что и обычный пакет.
Текущая версия API плагинов Composer — 2.3.0.
Пример файла действительного плагина composer.json (с пропущенной частью автозагрузки и необязательной зависимостью require-dev от composer/composer для автодополнения в IDE):
{
"name": "my/plugin-package",
"type": "composer-plugin",
"require": {
"composer-plugin-api": "^2.0"
},
"require-dev": {
"composer/composer": "^2.0"
},
"extra": {
"class": "My\\Plugin"
}
} Класс плагина
Каждый плагин должен предоставлять класс, который реализует Composer\Plugin\PluginInterface. Метод activate() плагина вызывается после загрузки плагина и получает экземпляр Composer\Composer, а также экземпляр Composer\IO\IOInterface. С помощью этих двух объектов можно прочитать всю конфигурацию и манипулировать внутренними объектами и состоянием по мере необходимости.
Пример:
<?php
namespace phpDocumentor\Composer;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
class TemplateInstallerPlugin implements PluginInterface
{
public function activate(Composer $composer, IOInterface $io)
{
$installer = new TemplateInstaller($io, $composer);
$composer->getInstallationManager()->addInstaller($installer);
}
} Обработчик событий
Кроме того, плагины могут реализовывать Composer\EventDispatcher\EventSubscriberInterface, чтобы их обработчики событий автоматически регистрировались в EventDispatcher при загрузке плагина.
Для регистрации метода для события реализуйте метод getSubscribedEvents() и верните массив. Ключ массива должен быть именем события, а значение — именем метода в этом классе, который будет вызван.
Примечание: Если вы не знаете, какое событие слушать, вы можете запустить команду Composer со переменной среды COMPOSER_DEBUG_EVENTS=1, что может помочь вам определить нужное событие.
public static function getSubscribedEvents()
{
return array(
'post-autoload-dump' => 'methodToBeCalled',
// ^ event name ^ ^ method name ^
);
} По умолчанию приоритет обработчика событий устанавливается в 0. Приоритет можно изменить, прикрепив кортеж, где первое значение — имя метода, как и раньше, а второе значение — целое число, представляющее приоритет. Более высокие целые числа соответствуют более высокому приоритету. Приоритет 2 вызывается перед приоритетом 1 и т. д.
public static function getSubscribedEvents()
{
return array(
// Will be called before events with priority 0
'post-autoload-dump' => array('methodToBeCalled', 1)
);
} Если нужно вызвать несколько методов, то к каждому событию можно прикрепить массив кортежей. Кортежи не должны включать приоритет. Если он опущен, он будет по умолчанию равен 0.
public static function getSubscribedEvents()
{
return array(
'post-autoload-dump' => array(
array('methodToBeCalled' ), // Priority defaults to 0
array('someOtherMethodName', 1), // This fires first
)
);
} Вот полный пример:
<?php
namespace Naderman\Composer\AWS;
use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PreFileDownloadEvent;
class AwsPlugin implements PluginInterface, EventSubscriberInterface
{
protected $composer;
protected $io;
public function activate(Composer $composer, IOInterface $io)
{
$this->composer = $composer;
$this->io = $io;
}
public function deactivate(Composer $composer, IOInterface $io)
{
}
public function uninstall(Composer $composer, IOInterface $io)
{
}
public static function getSubscribedEvents()
{
return array(
PluginEvents::PRE_FILE_DOWNLOAD => array(
array('onPreFileDownload', 0)
),
);
}
public function onPreFileDownload(PreFileDownloadEvent $event)
{
$protocol = parse_url($event->getProcessedUrl(), PHP_URL_SCHEME);
if ($protocol === 's3') {
// ...
}
}
} Возможности плагинов
Composer определяет стандартный набор возможностей, которые могут быть реализованы плагинами. Их цель — сделать экосистему плагинов более стабильной, поскольку это уменьшает необходимость вмешательства в Composer\Composer внутреннее состояние, обеспечив явные точки расширения для общих потребностей плагинов.
Классы плагинов с возможностями должны реализовывать интерфейс Composer\Plugin\Capable и объявлять свои возможности в методе getCapabilities(). Этот метод должен возвращать массив, с ключом как именем класса Возможности Composer, и значением как именем класса реализации Плагина указанной Возможности:
<?php
namespace My\Composer;
use Composer\Composer;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\Capable;
class Plugin implements PluginInterface, Capable
{
public function activate(Composer $composer, IOInterface $io)
{
}
public function getCapabilities()
{
return array(
'Composer\Plugin\Capability\CommandProvider' => 'My\Composer\CommandProvider',
);
}
} Поставщик команд
Возможность Composer\Plugin\Capability\CommandProvider позволяет регистрировать дополнительные команды для Composer:
<?php
namespace My\Composer;
use Composer\Plugin\Capability\CommandProvider as CommandProviderCapability;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Composer\Command\BaseCommand;
class CommandProvider implements CommandProviderCapability
{
public function getCommands()
{
return array(new Command);
}
}
class Command extends BaseCommand
{
protected function configure(): void
{
$this->setName('custom-plugin-command');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$output->writeln('Executing');
}
} Теперь команда custom-plugin-command доступна наряду с командами Composer.
Команды Composer основаны на Symfony Console Component.
Запуск плагинов вручную
Плагины для события можно запустить вручную с помощью команды run-script. Это работает так же, как запуск скриптов вручную.
Использование плагинов
Пакеты плагинов автоматически загружаются сразу после их установки и будут загружены при запуске Composer, если они найдены в списке установленных пакетов текущего проекта. Кроме того, все пакеты плагинов, установленные в каталоге COMPOSER_HOME с помощью глобальной команды Composer, загружаются перед загрузкой плагинов локального проекта.
Вы можете передать опцию
--no-pluginsв команды Composer, чтобы отключить все установленные плагины. Это может быть особенно полезно, если какой-либо из плагинов вызывает ошибки, и вы хотите обновить или удалить его.
Справочные инструменты плагинов
Начиная с Composer 2, из-за того, что DownloaderInterface иногда может возвращать Promises и быть разделен на больше шагов, чем раньше, мы предоставляем SyncHelper, чтобы упростить загрузку и установку пакетов.
Дополнительные атрибуты плагинов
Несколько специальных возможностей плагинов можно открыть с помощью дополнительных атрибутов в composer.json плагина.
class
См. выше для объяснения атрибута class и его работы.
plugin-modifies-downloads
Некоторые специальные плагины нуждаются в обновлении URL-адресов загрузки пакетов перед их загрузкой.
Начиная с Composer 2.0, все пакеты загружаются перед установкой. Это означает, что при первой установке ваш плагин ещё не установлен, когда происходит загрузка, и у него нет возможности обновить URL-адреса вовремя.
Указание {"extra": {"plugin-modifies-downloads": true}} в вашем composer.json намекнет Composer, что плагин должен быть установлен самостоятельно перед продолжением загрузки остальных пакетов. Это немного замедляет общий процесс установки, поэтому не используйте его в плагинах, которые в нём не нуждаются.
plugin-modifies-install-path
Некоторые специальные плагины изменяют путь установки пакетов.
Начиная с Composer 2.2.9, вы можете указать {"extra": {"plugin-modifies-install-path": true}} в вашем composer.json, чтобы намекнуть Composer, что плагин должен быть активирован как можно скорее, чтобы предотвратить нежелательные последствия от предположения Composer, что пакеты устанавливаются в другом месте, чем фактически.
Автозагрузка плагинов
Из-за того, что плагины загружаются Composer во время выполнения, и для обеспечения корректной работы плагинов, которые зависят от других пакетов, создаётся автозагрузчик во время выполнения, когда загружается плагин. Этот автозагрузчик настроен только на загрузку с зависимостями плагина, поэтому у вас может не быть доступа ко всем установленным пакетам.
Поддержка статического анализа
Начиная с Composer 2.3.7, мы поставляем файл конфигурации phpstan/rules.neon PHPStan, который предоставляет дополнительную проверку ошибок при работе с плагинами Composer.
Использование с PHPStan Extension Installer
Необходимые файлы конфигурации автоматически загружаются, если ваш проект плагина объявляет зависимость от phpstan/extension-installer.
Альтернативная ручная установка
Чтобы использовать его, ваш проект плагина Composer должен иметь файл конфигурации PHPStan, который включает файл phpstan/rules.neon:
includes:
- vendor/composer/composer/phpstan/rules.neon
// your remaining config..
© Nils Adermann, Jordi Boggiano
Licensed under the MIT License.
https://getcomposer.org/doc/articles/plugins.md