VOOZH about

URL: https://deepwiki.com/MahoCommerce/maho-composer-plugin/2.1-plugin-registration-and-activation

⇱ Plugin Registration and Activation | MahoCommerce/maho-composer-plugin | DeepWiki


Loading...
Menu

Plugin Registration and Activation

This document explains how the Maho Composer Plugin registers itself with Composer and how each of its three constituent plugins (AutoloadPlugin, ModmanPlugin, FileCopyPlugin) are discovered, instantiated, and activated by Composer's plugin API. This covers the static registration metadata in composer.json and the runtime activation lifecycle methods defined by the PluginInterface contract.

For information about the specific Composer events each plugin subscribes to and the temporal ordering of plugin execution, see Plugin Lifecycle and Events.

Composer Plugin API Requirements

The Maho Composer Plugin declares its compatibility with Composer's plugin system through explicit API version requirements in its dependency declarations:

DependencyVersion ConstraintPurpose
composer-plugin-api^2.1Defines the plugin interface contract (PluginInterface, EventSubscriberInterface)
composer-runtime-api^2Provides runtime access to installed package metadata during event handling

These requirements ensure that the plugin operates only in Composer environments that provide the necessary API surface. The plugin API version 2.1+ is required because it introduced the standardized activate(), deactivate(), and uninstall() lifecycle methods.

Sources:

Plugin Registration Metadata

The Maho Composer Plugin uses Composer's extra.class mechanism to register multiple plugin classes within a single package. This approach allows the plugin to decompose functionality into three specialized components that execute at different stages of the Composer workflow.


The registration declaration in composer.json specifies the three plugin class names:


Composer's plugin manager scans all installed packages with type: "composer-plugin" and reads their extra.class values. Each class name in this array must reference a fully-qualified class name that implements Composer\Plugin\PluginInterface.

Sources:

PluginInterface Contract Implementation

All three plugin classes implement the Composer\Plugin\PluginInterface contract, which defines three lifecycle methods that Composer invokes at specific points in the plugin's lifetime.


Each plugin class implements both PluginInterface and EventSubscriberInterface, allowing them to participate in Composer's event-driven architecture. The PluginInterface methods are invoked by Composer's plugin manager directly, while EventSubscriberInterface::getSubscribedEvents() returns a mapping of event names to callback methods.

Sources:

Activation Lifecycle

The activate() method is invoked by Composer immediately after the plugin class is instantiated. This method receives two parameters: a Composer instance providing access to the dependency graph and configuration, and an IOInterface instance for user interaction.

AutoloadPlugin Activation

The AutoloadPlugin stores references to the Composer instance and instantiates a Filesystem utility for path manipulation during autoload generation:


The stored Composer instance is later used to access the root package definition and modify its autoload configuration during the PRE_AUTOLOAD_DUMP event.

Sources:

ModmanPlugin Activation

The ModmanPlugin stores all three dependencies (IOInterface, Composer, Filesystem) because it requires I/O capabilities to report symlink creation status:


The Filesystem utility is used for both path normalization during modman file parsing and symlink creation in the deployment process.

Sources:

FileCopyPlugin Activation

The FileCopyPlugin has an empty activate() implementation because it defers initialization until its event callback executes:


This plugin uses a static $hasRun flag to prevent duplicate execution across multiple event invocations, and initializes its state (preserved files list, project directory) within the event callback itself.

Sources:

Plugin Discovery and Instantiation Flow


The plugin discovery and instantiation process occurs early in Composer's execution lifecycle, before any package installation or autoload generation begins. This ensures that plugins can subscribe to events that occur during the dependency resolution and installation phases.

Event Subscription Registration

After activation, Composer invokes getSubscribedEvents() on each plugin to build an event routing table:

PluginSubscribed EventsPurpose
AutoloadPluginScriptEvents::PRE_AUTOLOAD_DUMPModify autoload definition before Composer generates vendor/autoload.php
ModmanPluginPackageEvents::POST_PACKAGE_INSTALL
PackageEvents::POST_PACKAGE_UPDATE
PackageEvents::POST_PACKAGE_UNINSTALL
Create/update/remove module symlinks immediately after package operations
FileCopyPluginScriptEvents::POST_INSTALL_CMD
ScriptEvents::POST_UPDATE_CMD
ScriptEvents::POST_CREATE_PROJECT_CMD
Copy assets and executables after all packages are installed

These event subscriptions define the temporal ordering of plugin operations, with ModmanPlugin executing during package installation, AutoloadPlugin executing during autoload generation, and FileCopyPlugin executing after the entire command completes.

Sources:

Deactivation and Uninstallation

All three plugins provide empty implementations for deactivate() and uninstall() methods because they do not maintain persistent state that requires cleanup:


The deactivate() method is called when a plugin is disabled in the project configuration, while uninstall() is called when the plugin package is removed. Since the plugins operate on files managed by Composer (vendor directory) or generate derived artifacts (symlinks, copied files), no explicit cleanup is required—Composer handles removal of the vendor directory, and the generated artifacts are either regenerated on next install or can be safely left in place.

Sources: