0

I want to create a drush command that triggers some operations and subscribes to an event that is emitted when those operations are finished. Is this possible?

Specifically, the drush command imports feeds with $feed->import();, and after this is done, I want to listen for the event FeedsEvents::IMPORT_FINISHED in the command and react to that.

I don't understand how to do this conceptually because I can't figure out how I can get access to the Drupal flow of events from within drush. I tried to search the drush source for examples but the only use of EventSubscriber I could find was Command/GlobalOptionsEventListener.php, which is not a normal Drush command.

Drupal 11 and Drush 13 if it matters.

How can I subscribe to a Drupal event in a drush command?

4
  • 2
    I think this is impossible like defying gravity in the context of how this question is posed. These are different execution contexts: CLI and Web. The Drush job would have to be continually running, but crucially, Drush is a different program from Drupal and can't listen to its events. To do something like this the programs must communicate through a broker like Redis or RabbitMQ, or even via a database table. I will be happy to be wrong about this but I don't think I am.
    – mona lisa
    Commented Oct 12 at 1:37
  • Event handlers will fire if they are declared. You don't need to do anything special, just create an event handler in the normal Drupal way, and if declared correctly, it will fire regardless of whether the trigger happens through the UI or Drush.
    – Jaypan
    Commented Oct 12 at 20:11
  • @Jaypan My question may be worded confusingly, but what I want to do is "create an event handler that only fires for a specific Drush command." It should not fire if called by the UI or other cases. Commented Oct 13 at 0:47
  • 1
    Similar question for hooks drupal.stackexchange.com/questions/320242/…
    – 4uk4
    Commented Oct 13 at 7:53

1 Answer 1

3

Thanks to Jaypan's and 4uk4's comments, I found a way to do this.

The answer to "Can I add an event subscriber in a Drush command? (Get drush to subscribe to events?)" is no, you cannot.

However, if you change the question to "Can I add an event subscriber to a Drupal module that subscribes to an event and does specific processing if Drush was used to initiate the event?" the answer is yes.

Here's an example. This adds an event subscriber to the Feeds module that throws an exception if and only if drush was used to initiate an import which subsequently failed.

<?php

namespace Drupal\feeds\EventSubscriber;

use Drupal\feeds\Event\FeedsEvents;
use Drupal\feeds\Event\ImportFinishedEvent;
use Drupal\feeds\Exception\FeedsDrushException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Event listener that throws an exception if a drush-initiated import fails.
 */
class DrushImportExceptionSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events = [];
    $events[FeedsEvents::IMPORT_FINISHED][] = 'onImportFinished';
    return $events;
  }

  /**
   * Throws an exception if any drush-initiated imports failed.
   */
  public function onImportFinished(ImportFinishedEvent $event, string $event_name, EventDispatcherInterface $dispatcher): void {
    // Process only if the import was initiated by drush.
    if (PHP_SAPI === 'cli' && class_exists('\Drush\Drush')) {
      $feed = $event->getFeed();
      $process_state = $feed->getState('process');
      $failed_count = $process_state->failed;
      if ($failed_count > 0) {
        $feed_id = $feed->id();
        throw new FeedsDrushException("Feed with id $feed_id failed to import $failed_count items!");
      }
    }
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.