Spec-Zone.ru › Composer

Настройка и использование плагинов

Описание

Вы можете изменить или расширить функциональность Composer, создав собственные плагины. Например, если ваша среда предъявляет особые требования к поведению Composer, которые не относятся к большинству пользователей, или если вы хотите использовать Composer каким-то образом, который нежелателен для большинства пользователей.

В этих случаях вы можете рассмотреть возможность создания плагина для обработки вашей специфической логики.

Создание плагина

Плагин — это обычный пакет Composer, который поставляет свой код как часть пакета и может также зависеть от других пакетов.

Пакет плагина

Файл пакета такой же, как и любой другой файл пакета, но с следующими требованиями:

  1. Атрибут type должен быть composer-plugin.
  2. Атрибут extra должен содержать элемент class, определяющий имя класса плагина (включая пространство имён). Если пакет содержит несколько плагинов, это может быть массив имён классов.
  3. Необходимо потребовать специальный пакет, называемый 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API