Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Composer custom installer


May 25, 2021 Composer


Table of contents


Custom installer

Profile

Sometimes other actions need to be performed during the installation of the package, such as installing it in a vendor than the default vendor.

In these cases, you may want to consider creating a custom installer to handle specific logic.

Call the custom installer

Assuming that your project already has a custom installation module, how to call the installer in your package file correctly depending on the installation type becomes a problem.

See the next chapter on how to create a custom installer with instructions.

Any custom installer is recognized by the type property. Once confirmed, it completely overrides the default installer and executes its own installation logic.

An actual use case:

The special template for phpDocumentor needs to be installed in a directory other than /vendor. So they chose phpdocumentor-template and created a plug-in for that type to send their template to the correct directory.

In an example of such a template package, composer.json will use the following settings:

{
    "name": "phpdocumentor/template-responsive",
    "type": "phpdocumentor-template",
    "require": {
        "phpdocumentor/template-installer-plugin": "*"
    }
}

Important: To ensure that this template installer exists before the template package is installed, the template package must be written to rely on this installation package.

Create an installer

A custom installer usually exists as a Composer plug-in and contains a class that implements the interface of Composer\Installer\InstallerInterface

A basic installer plug-in must consist of 3 files:

  1. Package file: composer.json
  2. Plug-in classes, My\Project\Composer\Plugin.php where the class must implement Composer\Plugin\PluginInterface interface.
  3. Installer classes, such My\Project\Composer\Installer.php which must implement Composer\Installer\InstallerInterface interface.

composer.json

The package files here are the same as the normal resource pack, but the following conditions apply:

  1. The type property composer-plugin
  2. The extra property must contain class element, which defines the name of the plug-in class, including the namespace. If the package has more than one plug-in class, you can define it in the form of an array.

Instance:

{
    "name": "phpdocumentor/template-installer-plugin",
    "type": "composer-plugin",
    "license": "MIT",
    "autoload": {
        "psr-0": {"phpDocumentor\\Composer": "src/"}
    },
    "extra": {
        "class": "phpDocumentor\\Composer\\TemplateInstallerPlugin"
    },
    "require": {
        "composer-plugin-api": "1.0.0"
    }
}

Plug-in class

This class defines The Composer's plug-in, which Composer\Plugin\PluginInterface It can activate() in the activate() method.

This class can be placed anywhere, using any name, as long as it can be .class as defined in extra.class

Instance:

<?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);
    }
}

Custom installer class

This class is used to perform a custom installation process, and it must implement the interface of Composer\Installer\InstallerInterface inherit another installer class that implements this interface). It supports() method validation on the string defined in the installation type, and once passed, the corresponding installer is used.

Note: Choose your installation type name carefully, and it is recommended to follow this format: vendor-type For example: phpdocumentor-template .

The Installer International class defines the following methods (see source code for more detailed information):

  • Here, supports() test whether the installer name you published matches by the installation type (see example). Only properly matched resource packs will be installed using this installer.
  • IsInstalled() determines whether the supported resource pack is installed.
  • install() Here you can define the actions that need to be performed at installation time.
  • Update() Here you can define the actions that need to be performed at the time of the update. This is required when Composer calls to update parameters.
  • uninstall() Here you can define the actions that need to be performed when removing a package.
  • GetInstallPath() This method needs to return a location where the resource pack will be installed. le.

Instance:

<?php

namespace phpDocumentor\Composer;

use Composer\Package\PackageInterface;
use Composer\Installer\LibraryInstaller;

class TemplateInstaller extends LibraryInstaller
{
    /**
     * {@inheritDoc}
     */
    public function getPackageBasePath(PackageInterface $package)
    {
        $prefix = substr($package->getPrettyName(), 0, 23);
        if ('phpdocumentor/template-' !== $prefix) {
            throw new \InvalidArgumentException(
                'Unable to install template, phpdocumentor templates '
                .'should always start their package name with '
                .'"phpdocumentor/template-"'
            );
        }

        return 'data/templates/'.substr($package->getPrettyName(), 23);
    }

    /**
     * {@inheritDoc}
     */
    public function supports($packageType)
    {
        return 'phpdocumentor-template' === $packageType;
    }
}

This example demonstrates that simply Composer\Installer\LibraryInstaller to phpdocumentor/template- a completely different installation path with the rest.

Not /vendor directory, any resource pack that uses this installer will be placed in the /data/templates/<stripped name> directory.