Composer Scaffold plugin calls dispatch() instead of dispatchScript()

Created on 23 February 2022, almost 3 years ago
Updated 25 May 2024, 7 months ago

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

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.

πŸ› Bug report
Status

Fixed

Version

11.0 πŸ”₯

Component
ComposerΒ  β†’

Last updated 7 days ago

No maintainer
Created by

πŸ‡¬πŸ‡§United Kingdom joachim

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024