Problem/Motivation
In two places, the scaffold plugin does this:
// Call any pre-scaffold scripts that may be defined.
$dispatcher = new EventDispatcher($this->composer, $this->io);
$dispatcher->dispatch(self::PRE_DRUPAL_SCAFFOLD_CMD);
For a script event, dispatchScript() should be called, not dispatch().
An event triggered with dispatch() gets the wrong Event class passed to it as a parameter, and in particular, the IO object is not available.
Steps to reproduce
1. Create a plugin class with the following code
<?php
namespace YourNamespace\Composer\Plugin\YourPlugin;
use Composer\Composer;
use Composer\EventDispatcher\Event;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Script\Event;
use Composer\Plugin\PluginInterface;
/**
* Composer plugin for handling drupal scaffold.
*
* @internal
*/
class Plugin implements PluginInterface, EventSubscriberInterface {
/**
* {@inheritdoc}
*/
public function activate(Composer $composer, IOInterface $io) {
}
/**
* {@inheritdoc}
*/
public function deactivate(Composer $composer, IOInterface $io) {
}
/**
* {@inheritdoc}
*/
public function uninstall(Composer $composer, IOInterface $io) {
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
'pre-drupal-scaffold-cmd' => 'preDrupalScaffoldCmd',
'post-drupal-scaffold-cmd' => 'postDrupalScaffoldCmd',
];
}
public static function preDrupalScaffoldCmd(Event $event) {
$event->getIO()->write('Hello preDrupalScaffoldCmd');
}
public static function postDrupalScaffoldCmd(Event $event) {
$event->getIO()->write('Hello postDrupalScaffoldCmd');
}
}
2. Create a package with the following `composer.json` and place the file with Plugin class into `src` directory and provide references:
{
"name": "yournamespace/yourplugin",
"type": "composer-plugin",
"require": {
"php": ">=8.2",
"composer-plugin-api": "^2"
},
"autoload": {
"psr-4": {
"YourNamespace\\Composer\\Plugin\\YourPlugin\\": "src"
}
},
"extra": {
"class": "YourNamespace\\Composer\\Plugin\\YourPlugin\\Plugin"
}
}
3. Create a consumer website package:composer create-project drupal-composer/drupal-project:10.x-dev some-dir --no-interaction
4. Add your custom package as a dependency to the newly created project.
5. Run `composer drupal:scaffold`
6. Observe that plugin's listeners do not have access to the `getIO()` event.
Proposed resolution
Replace the $dispatcher->dispatch(self::PRE_DRUPAL_SCAFFOLD_CMD);
with $dispatcher->dispatchScript(self::PRE_DRUPAL_SCAFFOLD_CMD);
.
Do the same for $dispatcher->dispatch(self::POST_DRUPAL_SCAFFOLD_CMD);
.
This will allow to have access to IO and other event methods from the event handler.
Remaining tasks
Add code changeAdd tests
User interface changes
None
API changes
The event object passed to the event handler will be an instance of class Composer\Script\Event
.
Data model changes
None
Release notes snippet
Scaffold event handlers receive event object as an instance of class
Composer\Script\Event
.