Verified Commit 72926a56 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3441308 by phenaproxima: Dispatch an event when a recipe is applied

(cherry picked from commit 19dd1f3337964c409469dccfd50704bb62d1dcd4)
parent 3dcbb5ce
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\Core\Recipe;

use Symfony\Contracts\EventDispatcher\Event;

/**
 * Event dispatched after a recipe has been applied.
 *
 * Subscribers to this event should avoid modifying config or content, because
 * it is very likely that the recipe was applied as part of a chain of recipes,
 * so config and content are probably about to change again. This event is best
 * used for tasks like notifications, logging or updating a value in state.
 */
final class RecipeAppliedEvent extends Event {

  /**
   * Constructs a RecipeAppliedEvent object.
   *
   * @param \Drupal\Core\Recipe\Recipe $recipe
   *   The recipe that was applied.
   */
  public function __construct(public readonly Recipe $recipe) {
  }

}
+4 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\DefaultContent\Importer;
use Drupal\Core\DefaultContent\Finder;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;

/**
 * Applies a recipe.
@@ -32,6 +33,9 @@ public static function processRecipe(Recipe $recipe): void {
    static::processInstall($recipe->install, $recipe->config->getConfigStorage());
    static::processConfiguration($recipe->config);
    static::processContent($recipe->content);

    $event = new RecipeAppliedEvent($recipe);
    \Drupal::service(EventDispatcherInterface::class)->dispatch($event);
  }

  /**
+58 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\KernelTests\Core\Recipe;

use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Recipe\Recipe;
use Drupal\Core\Recipe\RecipeAppliedEvent;
use Drupal\Core\Recipe\RecipeRunner;
use Drupal\KernelTests\KernelTestBase;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * @group Recipe
 */
class RecipeEventsTest extends KernelTestBase implements EventSubscriberInterface {

  /**
   * The human-readable names of the recipes that have been applied.
   *
   * @var string[]
   */
  private array $recipesApplied = [];

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    return [
      RecipeAppliedEvent::class => 'onRecipeApply',
    ];
  }

  public function onRecipeApply(RecipeAppliedEvent $event): void {
    $this->recipesApplied[] = $event->recipe->name;
  }

  /**
   * {@inheritdoc}
   */
  public function register(ContainerBuilder $container): void {
    parent::register($container);

    // Every time the container is rebuilt, ensure this object is subscribing to
    // events.
    $container->getDefinition('event_dispatcher')
      ->addMethodCall('addSubscriber', [$this]);
  }

  public function testRecipeAppliedEvent(): void {
    $recipe = Recipe::createFromDirectory($this->getDrupalRoot() . '/core/tests/fixtures/recipes/recipe_include');
    RecipeRunner::processRecipe($recipe);

    $this->assertSame(['Install node with config', 'Recipe include'], $this->recipesApplied);
  }

}