VOOZH about

URL: https://deepwiki.com/MahoCommerce/maho-composer-plugin/2.2-plugin-lifecycle-and-events

⇱ Plugin Lifecycle and Events | MahoCommerce/maho-composer-plugin | DeepWiki


Loading...
Menu

Plugin Lifecycle and Events

Purpose and Scope

This document describes the lifecycle of the Maho Composer Plugin components and the Composer event system that orchestrates their execution. It covers how plugins integrate with Composer's event-driven architecture, the specific events each plugin subscribes to, and the temporal ordering of operations during a Composer workflow. For details on what each plugin does during its event handlers, see AutoloadPlugin Implementation, Modman File Format and Parsing, and Core File Copying Process.

Plugin Interface Implementation

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

Lifecycle Methods

The PluginInterface requires three methods:

MethodPurposeInvocation Timing
activate()Initialize plugin state and register with ComposerWhen plugin is first loaded
deactivate()Clean up temporary stateWhen plugin is disabled
uninstall()Remove persistent artifactsWhen plugin is removed from project

All three plugins implement these methods with minimal or no logic:

The activate() method receives two parameters:

  • Composer $composer: The main Composer instance providing access to configuration, packages, and repositories
  • IOInterface $io: The I/O interface for writing output and reading input

Sources: src/AutoloadPlugin.php51-63 src/ModmanPlugin.php26-39 src/FileCopyPlugin.php21-34

Event Subscription Mechanism

Plugins integrate with Composer's event system by implementing the EventSubscriberInterface, which requires a static getSubscribedEvents() method that returns a mapping of event names to handler method names.

Event Subscription Pattern


Each plugin's getSubscribedEvents() method returns an associative array where:

  • Keys are Composer event constant names (e.g., ScriptEvents::PRE_AUTOLOAD_DUMP)
  • Values are method names to invoke when the event fires (e.g., 'onPreAutoloadDumpCmd')

Sources: src/AutoloadPlugin.php5-11 src/ModmanPlugin.php5-14 src/FileCopyPlugin.php5-11

Composer Event Types and Plugin Subscriptions

The three plugins subscribe to different categories of Composer events, each operating at a different level of granularity.

Event Subscription Matrix


Event Subscriptions by Plugin

ModmanPlugin src/ModmanPlugin.php41-48:

  • PackageEvents::POST_PACKAGE_INSTALLonPostPackageInstall()
  • PackageEvents::POST_PACKAGE_UPDATEonPostPackageUpdate()
  • PackageEvents::POST_PACKAGE_UNINSTALLonPostPackageUninstall()

AutoloadPlugin src/AutoloadPlugin.php65-70:

  • ScriptEvents::PRE_AUTOLOAD_DUMPonPreAutoloadDumpCmd()

FileCopyPlugin src/FileCopyPlugin.php36-43:

  • ScriptEvents::POST_INSTALL_CMDonPostCmd()
  • ScriptEvents::POST_UPDATE_CMDonPostCmd()
  • ScriptEvents::POST_CREATE_PROJECT_CMDonPostCmd()

Sources: src/ModmanPlugin.php41-48 src/AutoloadPlugin.php65-70 src/FileCopyPlugin.php36-43

Temporal Event Execution Order

The order in which events fire during a Composer operation is critical to the plugin system's correct operation. Events progress through distinct phases, with each plugin operating at its designated stage.

Execution Sequence During composer install


Phase Dependencies and Rationale

PhasePluginRationale
1. ActivationAllPlugins initialize before any events fire
2. Package OperationsModmanPluginSymlinks must exist before autoload scanning
3. Autoload GenerationAutoloadPluginAutoload must be configured before file execution
4. Post-CommandFileCopyPluginAssets copied last, after all dependencies resolved

The ordering ensures:

  1. ModmanPlugin runs per-package: Symlinks are created immediately for each installed package, ensuring the directory structure exists before autoload scanning
  2. AutoloadPlugin runs once: Modifies Composer's autoload configuration before it generates vendor/autoload.php
  3. FileCopyPlugin runs once: Copies files after all packages are installed and autoloading is configured

Sources: src/ModmanPlugin.php50-71 src/AutoloadPlugin.php72-113 src/FileCopyPlugin.php45-108

Event Handler Methods and Parameters

Each event handler receives different event object types with specific information about the operation being performed.

ModmanPlugin Event Handlers

ModmanPlugin receives PackageEvent objects src/ModmanPlugin.php50-71 containing package-specific information:


Handler implementations:

AutoloadPlugin Event Handler

AutoloadPlugin receives a generic Event object src/AutoloadPlugin.php72-113:


Handler implementation:

  • onPreAutoloadDumpCmd() src/AutoloadPlugin.php72-113:
    • Generates include paths, PSR-0 mappings, and class maps via AutoloadRuntime
    • Checks optimize flag to determine whether to use PSR-0 prefixes or full class map
    • Modifies RootPackage autoload definition before Composer generates autoloader

FileCopyPlugin Event Handler

FileCopyPlugin receives a generic Event object src/FileCopyPlugin.php45-108 and implements a run-once pattern:


Handler implementation:

Sources: src/ModmanPlugin.php50-71 src/AutoloadPlugin.php72-113 src/FileCopyPlugin.php45-108

Event Handler State Management

Run-Once Pattern in FileCopyPlugin

FileCopyPlugin subscribes to three different command completion events but should only execute once per Composer invocation. It implements a simple static flag pattern src/FileCopyPlugin.php14:


The handler checks this flag at the beginning src/FileCopyPlugin.php47-51:

  • If $hasRun is true, return immediately
  • Otherwise, set $hasRun = true and proceed with file copying

This ensures that whether the user runs composer install, composer update, or composer create-project, the file copying logic executes exactly once after all packages are installed.

Stateless Pattern in ModmanPlugin

ModmanPlugin event handlers are stateless - each package event is handled independently src/ModmanPlugin.php50-71 The pattern is:

  • Install/Update: undeploy() then deploy() - ensures clean symlink state
  • Uninstall: undeploy() only - removes symlinks

This design allows package operations to be processed in any order without side effects.

Configuration-Dependent Pattern in AutoloadPlugin

AutoloadPlugin's behavior changes based on Composer's optimize flag src/AutoloadPlugin.php98-109:

  • Without --optimize: Generates PSR-0 prefix mappings for runtime class loading
  • With --optimize: Generates complete class map for optimized autoloading

The event handler reads this from $event->getFlags()['optimize'] and adjusts its output accordingly.

Sources: src/FileCopyPlugin.php14 src/FileCopyPlugin.php47-51 src/ModmanPlugin.php50-71 src/AutoloadPlugin.php98-109