5.3 KiB
Setting up and using plugins
Synopsis
You may wish to alter or expand Composer's functionality with your own. For example if your environment poses special requirements on the behaviour of Composer which do not apply to the majority of its users or if you wish to accomplish something with composer in a way that is not desired by most users.
In these cases you could consider creating a plugin to handle your specific logic.
Creating a Plugin
A plugin is a regular Composer package which ships its code as part of the package and may also depend on further packages.
Plugin Package
The package file is the same as any other package file but with the following requirements:
- The type attribute must be
composer-plugin
. - The extra attribute must contain an element
class
defining the class name of the plugin (including namespace). If a package contains multiple plugins, this can be array of class names. - You must require the special package called
composer-plugin-api
to define which Plugin API versions your plugin is compatible with.
The required version of the composer-plugin-api
follows the same rules
as a normal package's, except for the 1.0
, 1.0.0
and 1.0.0.0
exact
values. In only these three cases, Composer will assume your plugin
actually meant ^1.0
instead. This was introduced to maintain BC with
the old style of declaring the Plugin API version.
In other words, "require": { "composer-plugin-api": "1.0.0" }
means
"require": { "composer-plugin-api": "^1.0" }
.
The current composer plugin API version is 1.0.0.
An example of a valid plugin composer.json
file (with the autoloading
part omitted):
{
"name": "my/plugin-package",
"type": "composer-plugin",
"require": {
"composer-plugin-api": "~1.0"
},
"extra": {
"class": "My\\Plugin"
}
}
Plugin Class
Every plugin has to supply a class which implements the
Composer\Plugin\PluginInterface
. The activate()
method of the plugin
is called after the plugin is loaded and receives an instance of
Composer\Composer
as well as an instance of
Composer\IO\IOInterface
. Using these two objects all configuration can
be read and all internal objects and state can be manipulated as desired.
Example:
<?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);
}
}
Event Handler
Furthermore plugins may implement the
Composer\EventDispatcher\EventSubscriberInterface
in order to have its
event handlers automatically registered with the EventDispatcher
when the
plugin is loaded.
Plugin can subscribe to any of the available script events.
Example:
<?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 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') {
$awsClient = new AwsClient($this->io, $this->composer->getConfig());
$s3RemoteFilesystem = new S3RemoteFilesystem($this->io, $event->getRemoteFilesystem()->getOptions(), $awsClient);
$event->setRemoteFilesystem($s3RemoteFilesystem);
}
}
}
Using Plugins
Plugin packages are automatically loaded as soon as they are installed and will
be loaded when composer starts up if they are found in the current project's
list of installed packages. Additionally all plugin packages installed in the
COMPOSER_HOME
directory using the composer global command are loaded before
local project plugins are loaded.
You may pass the
--no-plugins
option to composer commands to disable all installed plugins. This may be particularly helpful if any of the plugins causes errors and you wish to update or uninstall it.