From 62fe82b31229c5415846c2e327aa9b21a9534547 Mon Sep 17 00:00:00 2001 From: phenaproxima <phenaproxima@205645.no-reply.drupal.org> Date: Mon, 25 Oct 2021 16:49:23 +0000 Subject: [PATCH] Issue #3245766 by phenaproxima, tedbow: Fire events throughout Package Manager's stage life cycle --- package_manager/package_manager.services.yml | 1 + package_manager/src/Event/PostApplyEvent.php | 9 ++ package_manager/src/Event/PostCreateEvent.php | 9 ++ .../src/Event/PostDestroyEvent.php | 9 ++ .../src/Event/PostRequireEvent.php | 9 ++ package_manager/src/Event/PreApplyEvent.php | 9 ++ package_manager/src/Event/PreCreateEvent.php | 9 ++ package_manager/src/Event/PreDestroyEvent.php | 9 ++ package_manager/src/Event/PreRequireEvent.php | 9 ++ package_manager/src/Event/StageEvent.php | 11 +++ package_manager/src/Stage.php | 32 ++++++- .../tests/src/Kernel/StageEventsTest.php | 89 +++++++++++++++++++ .../Functional/FileSystemOperationsTest.php | 3 +- 13 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 package_manager/src/Event/PostApplyEvent.php create mode 100644 package_manager/src/Event/PostCreateEvent.php create mode 100644 package_manager/src/Event/PostDestroyEvent.php create mode 100644 package_manager/src/Event/PostRequireEvent.php create mode 100644 package_manager/src/Event/PreApplyEvent.php create mode 100644 package_manager/src/Event/PreCreateEvent.php create mode 100644 package_manager/src/Event/PreDestroyEvent.php create mode 100644 package_manager/src/Event/PreRequireEvent.php create mode 100644 package_manager/src/Event/StageEvent.php create mode 100644 package_manager/tests/src/Kernel/StageEventsTest.php diff --git a/package_manager/package_manager.services.yml b/package_manager/package_manager.services.yml index 41deacfbde..c083562388 100644 --- a/package_manager/package_manager.services.yml +++ b/package_manager/package_manager.services.yml @@ -94,3 +94,4 @@ services: - '@package_manager.stager' - '@package_manager.committer' - '@package_manager.cleaner' + - '@event_dispatcher' diff --git a/package_manager/src/Event/PostApplyEvent.php b/package_manager/src/Event/PostApplyEvent.php new file mode 100644 index 0000000000..d2a9693cf9 --- /dev/null +++ b/package_manager/src/Event/PostApplyEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired after staged changes are synced to the active directory. + */ +class PostApplyEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PostCreateEvent.php b/package_manager/src/Event/PostCreateEvent.php new file mode 100644 index 0000000000..104bc78ad6 --- /dev/null +++ b/package_manager/src/Event/PostCreateEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired after a staging area has been created. + */ +class PostCreateEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PostDestroyEvent.php b/package_manager/src/Event/PostDestroyEvent.php new file mode 100644 index 0000000000..3388a988e1 --- /dev/null +++ b/package_manager/src/Event/PostDestroyEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired after the staging area is destroyed. + */ +class PostDestroyEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PostRequireEvent.php b/package_manager/src/Event/PostRequireEvent.php new file mode 100644 index 0000000000..55b4184dd3 --- /dev/null +++ b/package_manager/src/Event/PostRequireEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired after packages are added to the staging area. + */ +class PostRequireEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PreApplyEvent.php b/package_manager/src/Event/PreApplyEvent.php new file mode 100644 index 0000000000..3ffdf0d175 --- /dev/null +++ b/package_manager/src/Event/PreApplyEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired before staged changes are synced to the active directory. + */ +class PreApplyEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PreCreateEvent.php b/package_manager/src/Event/PreCreateEvent.php new file mode 100644 index 0000000000..c893738bee --- /dev/null +++ b/package_manager/src/Event/PreCreateEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired before a staging area is created. + */ +class PreCreateEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PreDestroyEvent.php b/package_manager/src/Event/PreDestroyEvent.php new file mode 100644 index 0000000000..1d75a7fe54 --- /dev/null +++ b/package_manager/src/Event/PreDestroyEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired before the staging area is destroyed. + */ +class PreDestroyEvent extends StageEvent { +} diff --git a/package_manager/src/Event/PreRequireEvent.php b/package_manager/src/Event/PreRequireEvent.php new file mode 100644 index 0000000000..93a122ad6d --- /dev/null +++ b/package_manager/src/Event/PreRequireEvent.php @@ -0,0 +1,9 @@ +<?php + +namespace Drupal\package_manager\Event; + +/** + * Event fired before packages are added to the staging area. + */ +class PreRequireEvent extends StageEvent { +} diff --git a/package_manager/src/Event/StageEvent.php b/package_manager/src/Event/StageEvent.php new file mode 100644 index 0000000000..2aeadbf810 --- /dev/null +++ b/package_manager/src/Event/StageEvent.php @@ -0,0 +1,11 @@ +<?php + +namespace Drupal\package_manager\Event; + +use Symfony\Contracts\EventDispatcher\Event; + +/** + * Base class for all events related to the life cycle of the staging area. + */ +abstract class StageEvent extends Event { +} diff --git a/package_manager/src/Stage.php b/package_manager/src/Stage.php index d3a84009b5..8f4e9e16d2 100644 --- a/package_manager/src/Stage.php +++ b/package_manager/src/Stage.php @@ -2,10 +2,19 @@ namespace Drupal\package_manager; +use Drupal\package_manager\Event\PostApplyEvent; +use Drupal\package_manager\Event\PostCreateEvent; +use Drupal\package_manager\Event\PostDestroyEvent; +use Drupal\package_manager\Event\PostRequireEvent; +use Drupal\package_manager\Event\PreApplyEvent; +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\PreDestroyEvent; +use Drupal\package_manager\Event\PreRequireEvent; use PhpTuf\ComposerStager\Domain\BeginnerInterface; use PhpTuf\ComposerStager\Domain\CleanerInterface; use PhpTuf\ComposerStager\Domain\CommitterInterface; use PhpTuf\ComposerStager\Domain\StagerInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Creates and manages a staging area in which to install or update code. @@ -52,6 +61,13 @@ class Stage { */ protected $cleaner; + /** + * The event dispatcher service. + * + * @var \Symfony\Contracts\EventDispatcher\EventDispatcherInterface + */ + protected $eventDispatcher; + /** * Constructs a new Stage object. * @@ -65,13 +81,16 @@ class Stage { * The committer service from Composer Stager. * @param \PhpTuf\ComposerStager\Domain\CleanerInterface $cleaner * The cleaner service from Composer Stager. + * @param \Symfony\Contracts\EventDispatcher\EventDispatcherInterface $event_dispatcher + * The event dispatcher service. */ - public function __construct(PathLocator $path_locator, BeginnerInterface $beginner, StagerInterface $stager, CommitterInterface $committer, CleanerInterface $cleaner) { + public function __construct(PathLocator $path_locator, BeginnerInterface $beginner, StagerInterface $stager, CommitterInterface $committer, CleanerInterface $cleaner, EventDispatcherInterface $event_dispatcher) { $this->pathLocator = $path_locator; $this->beginner = $beginner; $this->stager = $stager; $this->committer = $committer; $this->cleaner = $cleaner; + $this->eventDispatcher = $event_dispatcher; } /** @@ -85,7 +104,10 @@ class Stage { public function create(?array $exclusions = []): void { $active_dir = $this->pathLocator->getActiveDirectory(); $stage_dir = $this->pathLocator->getStageDirectory(); + + $this->eventDispatcher->dispatch(new PreCreateEvent()); $this->beginner->begin($active_dir, $stage_dir, $exclusions); + $this->eventDispatcher->dispatch(new PostCreateEvent()); } /** @@ -97,7 +119,10 @@ class Stage { public function require(array $constraints): void { $command = array_merge(['require'], $constraints); $command[] = '--update-with-all-dependencies'; + + $this->eventDispatcher->dispatch(new PreRequireEvent()); $this->stager->stage($command, $this->pathLocator->getStageDirectory()); + $this->eventDispatcher->dispatch(new PostRequireEvent()); } /** @@ -111,17 +136,22 @@ class Stage { public function apply(?array $exclusions = []): void { $active_dir = $this->pathLocator->getActiveDirectory(); $stage_dir = $this->pathLocator->getStageDirectory(); + + $this->eventDispatcher->dispatch(new PreApplyEvent()); $this->committer->commit($stage_dir, $active_dir, $exclusions); + $this->eventDispatcher->dispatch(new PostApplyEvent()); } /** * Deletes the staging area. */ public function destroy(): void { + $this->eventDispatcher->dispatch(new PreDestroyEvent()); $stage_dir = $this->pathLocator->getStageDirectory(); if (is_dir($stage_dir)) { $this->cleaner->clean($stage_dir); } + $this->eventDispatcher->dispatch(new PostDestroyEvent()); } } diff --git a/package_manager/tests/src/Kernel/StageEventsTest.php b/package_manager/tests/src/Kernel/StageEventsTest.php new file mode 100644 index 0000000000..aba696089c --- /dev/null +++ b/package_manager/tests/src/Kernel/StageEventsTest.php @@ -0,0 +1,89 @@ +<?php + +namespace Drupal\Tests\package_manager\Kernel; + +use Drupal\KernelTests\KernelTestBase; +use Drupal\package_manager\Event\PostApplyEvent; +use Drupal\package_manager\Event\PostCreateEvent; +use Drupal\package_manager\Event\PostDestroyEvent; +use Drupal\package_manager\Event\PostRequireEvent; +use Drupal\package_manager\Event\PreApplyEvent; +use Drupal\package_manager\Event\PreCreateEvent; +use Drupal\package_manager\Event\PreDestroyEvent; +use Drupal\package_manager\Event\PreRequireEvent; +use Drupal\package_manager\Event\StageEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; + +/** + * Tests that the staging area fires events during its lifecycle. + * + * @group package_manager + */ +class StageEventsTest extends KernelTestBase implements EventSubscriberInterface { + + /** + * {@inheritdoc} + */ + protected static $modules = [ + 'package_manager', + 'package_manager_bypass', + ]; + + /** + * The events that were fired, in the order they were fired. + * + * @var string[] + */ + private $events = []; + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() { + return [ + PreCreateEvent::class => 'handleEvent', + PostCreateEvent::class => 'handleEvent', + PreRequireEvent::class => 'handleEvent', + PostRequireEvent::class => 'handleEvent', + PreApplyEvent::class => 'handleEvent', + PostApplyEvent::class => 'handleEvent', + PreDestroyEvent::class => 'handleEvent', + PostDestroyEvent::class => 'handleEvent', + ]; + } + + /** + * Handles a staging area life cycle event. + * + * @param \Drupal\package_manager\Event\StageEvent $event + * The event object. + */ + public function handleEvent(StageEvent $event): void { + array_push($this->events, get_class($event)); + } + + /** + * Tests that the staging area fires life cycle events in a specific order. + */ + public function testEvents(): void { + $this->container->get('event_dispatcher')->addSubscriber($this); + + $stage = $this->container->get('package_manager.stage'); + $stage->create(); + $stage->require(['ext-json:*']); + $stage->apply(); + $stage->destroy(); + + $this->assertSame($this->events, [ + PreCreateEvent::class, + PostCreateEvent::class, + PreRequireEvent::class, + PostRequireEvent::class, + PreApplyEvent::class, + PostApplyEvent::class, + PreDestroyEvent::class, + PostDestroyEvent::class, + ]); + } + +} diff --git a/tests/src/Functional/FileSystemOperationsTest.php b/tests/src/Functional/FileSystemOperationsTest.php index fe42f99893..78a481fb0d 100644 --- a/tests/src/Functional/FileSystemOperationsTest.php +++ b/tests/src/Functional/FileSystemOperationsTest.php @@ -75,7 +75,8 @@ class FileSystemOperationsTest extends AutomaticUpdatesFunctionalTestBase { $this->container->get('package_manager.beginner'), $this->container->get('package_manager.stager'), $this->container->get('package_manager.committer'), - $cleaner + $cleaner, + $this->container->get('event_dispatcher') ); $this->updater = new Updater( -- GitLab