From 35b1178e1a725694d358668eed78731af2671c65 Mon Sep 17 00:00:00 2001 From: jiaweipan <1028244674@qq.com> Date: Sun, 6 Aug 2023 13:47:40 +0800 Subject: [PATCH] Add TransitionListener and add test --- src/Dispatcher/AbstractSubject.php | 7 +++++- src/Dispatcher/Dispatcher.php | 4 +--- src/StateMachine/StateMachineImpl.php | 16 +++++++++++++ src/StateMachine/StateMachineInterface.php | 4 ++++ tests/StateMachineTest.php | 26 ++++++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/Dispatcher/AbstractSubject.php b/src/Dispatcher/AbstractSubject.php index b185dd2..1e91a09 100644 --- a/src/Dispatcher/AbstractSubject.php +++ b/src/Dispatcher/AbstractSubject.php @@ -5,6 +5,7 @@ namespace DDDPHP\StateMachine\Dispatcher; use DDDPHP\StateMachine\Event\EventInterface; +use DDDPHP\StateMachine\StateMachine\StateMachineException; use Psr\EventDispatcher\EventDispatcherInterface; use Psr\EventDispatcher\ListenerProviderInterface; @@ -20,7 +21,11 @@ public function __construct() } public function addListener(EventInterface $event, callable $listener): void { - $this->listeners[$event::class][] = $listener; + $classImplements = array_values(class_implements($event)); + if (empty($classImplements[0])) { + throw new StateMachineException(" the event must implements an interface"); + } + $this->listeners[$classImplements[0]][] = $listener; } public function fireEvent(EventInterface $event): void diff --git a/src/Dispatcher/Dispatcher.php b/src/Dispatcher/Dispatcher.php index 27151c6..d2293f1 100644 --- a/src/Dispatcher/Dispatcher.php +++ b/src/Dispatcher/Dispatcher.php @@ -16,9 +16,7 @@ final class Dispatcher implements EventDispatcherInterface { private ListenerProviderInterface $listenerProvider; - /** - * @param ListenerProviderInterface $listenerProvider - */ + public function __construct(ListenerProviderInterface $listenerProvider) { $this->listenerProvider = $listenerProvider; diff --git a/src/StateMachine/StateMachineImpl.php b/src/StateMachine/StateMachineImpl.php index 648478a..ac904e1 100644 --- a/src/StateMachine/StateMachineImpl.php +++ b/src/StateMachine/StateMachineImpl.php @@ -119,4 +119,20 @@ public function setReady(bool $ready): void { $this->ready = $ready; } + + public function addTransitionPreListener(callable $listener): void + { + $this->addListener( + new class () implements PreTransitionEventInterface {}, + $listener + ); + } + + public function addTransitionPostListener(callable $listener): void + { + $this->addListener( + new class () implements PostTransitionEventInterface {}, + $listener + ); + } } diff --git a/src/StateMachine/StateMachineInterface.php b/src/StateMachine/StateMachineInterface.php index 852866c..9803e7f 100644 --- a/src/StateMachine/StateMachineInterface.php +++ b/src/StateMachine/StateMachineInterface.php @@ -15,4 +15,8 @@ public function fire(string $sourceStateId, string $event, $context): string; public function getMachineId(): string; public function showStateMachine(): void; + + public function addTransitionPreListener(callable $listener): void; + + public function addTransitionPostListener(callable $listener): void; } diff --git a/tests/StateMachineTest.php b/tests/StateMachineTest.php index 35a0d67..d4cb128 100644 --- a/tests/StateMachineTest.php +++ b/tests/StateMachineTest.php @@ -7,6 +7,7 @@ use DDDPHP\StateMachine\Action\ActionInterface; use DDDPHP\StateMachine\Builder\StateMachineBuilderFactory; use DDDPHP\StateMachine\Condition\ConditionInterface; +use DDDPHP\StateMachine\Event\PreTransitionEventInterface; use DDDPHP\StateMachine\StateMachine\StateMachineInterface; use PHPUnit\Framework\TestCase; @@ -87,6 +88,31 @@ public function testInternalNormal(): void $this->assertEquals(self::STATE1, $target); } + public function testTransitionListener() :void + { + $preTransitionListenerCount = 0; + $postTransitionListenerCount = 0; + $builder = StateMachineBuilderFactory::create(); + $builder->externalTransitions() + ->fromAmong(self::STATE1, self::STATE2, self::STATE3) + ->to(self::STATE4) + ->on(self::EVENT1) + ->when($this->checkCondition()) + ->perform($this->doAction()); + $stateMachine = $builder->build(self::MACHINE_ID . "transition-listener"); + + $stateMachine->addTransitionPreListener(function () use (&$preTransitionListenerCount) { + $preTransitionListenerCount += 1; + }); + $stateMachine->addTransitionPostListener(function () use (&$postTransitionListenerCount) { + $postTransitionListenerCount += 2; + }); + + $stateMachine->fire(self::STATE2, self::EVENT1, $this->context); + + $this->assertEquals(1, $preTransitionListenerCount); + $this->assertEquals(2, $postTransitionListenerCount); + } public function testExternalInternalNormal(): void { $stateMachine = $this->buildStateMachine();