From 1bbc333b31041c2f2e5c7c118f67228732c2890c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:25:18 +0300 Subject: [PATCH 01/33] test: Introduce CalculatorMachine (WEB-4344) --- tests/Stubs/Machines/CalculatorMachine.php | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 tests/Stubs/Machines/CalculatorMachine.php diff --git a/tests/Stubs/Machines/CalculatorMachine.php b/tests/Stubs/Machines/CalculatorMachine.php new file mode 100644 index 0000000..b9c5af1 --- /dev/null +++ b/tests/Stubs/Machines/CalculatorMachine.php @@ -0,0 +1,51 @@ + 'ready', + 'context' => [ + 'result' => 0, + ], + 'states' => [ + 'ready' => [ + 'on' => [ + 'ADD' => ['actions' => 'additionAction'], + 'SUB' => ['actions' => 'subtractionAction'], + 'MUL' => ['actions' => 'multiplicationAction'], + 'DIV' => ['actions' => 'divisionAction'], + ], + ], + ], + ], + behavior: [ + 'actions' => [ + 'additionAction' => function (ContextManager $c, EventDefinition $e): void { + $c->result = $c->result + $e->payload['value']; + }, + 'subtractionAction' => function (ContextManager $ctx, EventDefinition $evt): void { + $ctx->result = $ctx->result - $evt->payload['value']; + }, + 'multiplicationAction' => function (ContextManager $contextManager, EventDefinition $eventDefinition): void { + $contextManager->result = $contextManager->result * $eventDefinition->payload['value']; + }, + 'divisionAction' => function (ContextManager $manager, EventDefinition $event): void { + $manager->result = $manager->result / $event->payload['value']; + }, + ], + ], + ); + } +} From 11c1317c8ba733ee2995e99193ebb5cefe8126e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:26:20 +0300 Subject: [PATCH 02/33] feat: Ability to inject ContextManager into behaviors (WEB-4344) --- src/Definition/MachineDefinition.php | 18 ++++++++++--- tests/BehaviorDependencyInjectionTest.php | 31 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 tests/BehaviorDependencyInjectionTest.php diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index c2ef132..b59e2a3 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -4,6 +4,7 @@ namespace Tarfinlabs\EventMachine\Definition; +use ReflectionFunction; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; @@ -686,8 +687,9 @@ public function transition( * action definition, and if the action behavior is callable, it * executes it using the context and event payload. * - * @param string $actionDefinition The action definition, either a class - * @param EventBehavior|null $eventBehavior The event (optional). + * @param string $actionDefinition The action definition, either a class + * @param EventBehavior|null $eventBehavior The event (optional). + * @throws \ReflectionException */ public function runAction( string $actionDefinition, @@ -724,8 +726,18 @@ public function runAction( // Get the number of events in the queue before the action is executed. $numberOfEventsInQueue = $this->eventQueue->count(); + $actionBehaviorParameters = []; + /** @var \ReflectionParameter $parameter */ + foreach ((new ReflectionFunction($actionBehavior))->getParameters() as $parameter) { + $value = match ($parameter->getType()->getName()) { + ContextManager::class => $state->context, + default => null, + }; + $actionBehaviorParameters[$parameter->getName()] = $value; + } + // Execute the action behavior. - $actionBehavior($state->context, $eventBehavior, $actionArguments); + $actionBehavior(...$actionBehaviorParameters); // Get the number of events in the queue after the action is executed. $newNumberOfEventsInQueue = $this->eventQueue->count(); diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php new file mode 100644 index 0000000..2a09e68 --- /dev/null +++ b/tests/BehaviorDependencyInjectionTest.php @@ -0,0 +1,31 @@ + 'ready', + 'states' => [ + 'ready' => [ + 'on' => [ + 'CTX' => ['actions' => 'contextAction'], + ], + ], + ], + ], + behavior: [ + 'actions' => [ + 'contextAction' => function (ContextManager $c): void { + expect($c)->toBeInstanceOf(ContextManager::class); + }, + ], + ], + )); + + $machine->send(['type' => 'CTX']); +}); From 55efbe9a5e16faac5f130a1c3094bf8928702bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:28:13 +0300 Subject: [PATCH 03/33] feat: Ability to inject EventBehavior into behaviors (WEB-4344) --- src/Definition/MachineDefinition.php | 6 +++--- tests/BehaviorDependencyInjectionTest.php | 9 +++++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index b59e2a3..97a13b3 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -687,9 +687,8 @@ public function transition( * action definition, and if the action behavior is callable, it * executes it using the context and event payload. * - * @param string $actionDefinition The action definition, either a class - * @param EventBehavior|null $eventBehavior The event (optional). - * @throws \ReflectionException + * @param string $actionDefinition The action definition, either a class + * @param EventBehavior|null $eventBehavior The event (optional). */ public function runAction( string $actionDefinition, @@ -731,6 +730,7 @@ public function runAction( foreach ((new ReflectionFunction($actionBehavior))->getParameters() as $parameter) { $value = match ($parameter->getType()->getName()) { ContextManager::class => $state->context, + EventBehavior::class => $eventBehavior, default => null, }; $actionBehaviorParameters[$parameter->getName()] = $value; diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php index 2a09e68..11a9bd3 100644 --- a/tests/BehaviorDependencyInjectionTest.php +++ b/tests/BehaviorDependencyInjectionTest.php @@ -4,9 +4,10 @@ use Tarfinlabs\EventMachine\Actor\Machine; use Tarfinlabs\EventMachine\ContextManager; +use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Definition\MachineDefinition; -it('it can inject ContextManager', function (): void { +it('it can inject requested parameters', function (): void { $machine = Machine::create(MachineDefinition::define( config: [ 'initial' => 'ready', @@ -20,8 +21,12 @@ ], behavior: [ 'actions' => [ - 'contextAction' => function (ContextManager $c): void { + 'contextAction' => function ( + ContextManager $c, + EventBehavior $e, + ): void { expect($c)->toBeInstanceOf(ContextManager::class); + expect($e)->toBeInstanceOf(EventBehavior::class); }, ], ], From f6828238672ad0f6e1adf1dfa5ccd2124bdf7190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:30:48 +0300 Subject: [PATCH 04/33] test: Updated the test 'it can inject requested parameters' (WEB-4344) --- tests/BehaviorDependencyInjectionTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php index 11a9bd3..e4a7a53 100644 --- a/tests/BehaviorDependencyInjectionTest.php +++ b/tests/BehaviorDependencyInjectionTest.php @@ -10,6 +10,9 @@ it('it can inject requested parameters', function (): void { $machine = Machine::create(MachineDefinition::define( config: [ + 'context' => [ + 'value' => 1, + ], 'initial' => 'ready', 'states' => [ 'ready' => [ @@ -26,6 +29,8 @@ EventBehavior $e, ): void { expect($c)->toBeInstanceOf(ContextManager::class); + expect($c->value)->toBe(1); + expect($e)->toBeInstanceOf(EventBehavior::class); }, ], From b2f6999f3b393988973d79d36940ea85063123dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:32:30 +0300 Subject: [PATCH 05/33] feat: Add assertion for `EventBehavior` type in `BehaviorDependencyInjectionTest.php` (WEB-4344) --- tests/BehaviorDependencyInjectionTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php index e4a7a53..7dc3b6f 100644 --- a/tests/BehaviorDependencyInjectionTest.php +++ b/tests/BehaviorDependencyInjectionTest.php @@ -32,6 +32,7 @@ expect($c->value)->toBe(1); expect($e)->toBeInstanceOf(EventBehavior::class); + expect($e->type)->toBe('CTX'); }, ], ], From c9e525f5d7349c413f9eb1388891a42925898652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:34:26 +0300 Subject: [PATCH 06/33] feat: Add `State` parameter to `contextAction` in `BehaviorDependencyInjectionTest.php` (WEB-4344) --- src/Definition/MachineDefinition.php | 1 + tests/BehaviorDependencyInjectionTest.php | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 97a13b3..dc6eebd 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -731,6 +731,7 @@ public function runAction( $value = match ($parameter->getType()->getName()) { ContextManager::class => $state->context, EventBehavior::class => $eventBehavior, + State::class => $state, default => null, }; $actionBehaviorParameters[$parameter->getName()] = $value; diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php index 7dc3b6f..78f58c9 100644 --- a/tests/BehaviorDependencyInjectionTest.php +++ b/tests/BehaviorDependencyInjectionTest.php @@ -2,6 +2,7 @@ declare(strict_types=1); +use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\Actor\Machine; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\EventBehavior; @@ -27,12 +28,16 @@ 'contextAction' => function ( ContextManager $c, EventBehavior $e, + State $s, ): void { expect($c)->toBeInstanceOf(ContextManager::class); expect($c->value)->toBe(1); expect($e)->toBeInstanceOf(EventBehavior::class); expect($e->type)->toBe('CTX'); + + expect($s)->toBeInstanceOf(State::class); + expect($s->value)->toBe(['machine.ready']); }, ], ], From b7671e0757a7bd15c74964547deaefc3f4e0797c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:43:06 +0300 Subject: [PATCH 07/33] feat: Add `EventCollection` class in `src/EventCollection.php` (WEB-4344) This commit introduces a new class `EventCollection` in `src/EventCollection.php`. The `EventCollection` class extends the `Illuminate\Support\Collection` class. --- src/Actor/State.php | 5 +++-- src/EventCollection.php | 11 +++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 src/EventCollection.php diff --git a/src/Actor/State.php b/src/Actor/State.php index a92165c..6664365 100644 --- a/src/Actor/State.php +++ b/src/Actor/State.php @@ -8,6 +8,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Facades\Log; use Tarfinlabs\EventMachine\ContextManager; +use Tarfinlabs\EventMachine\EventCollection; use Tarfinlabs\EventMachine\Enums\SourceType; use Tarfinlabs\EventMachine\Enums\InternalEvent; use Tarfinlabs\EventMachine\Models\MachineEvent; @@ -41,9 +42,9 @@ public function __construct( public ContextManager $context, public ?StateDefinition $currentStateDefinition, public ?EventBehavior $currentEventBehavior = null, - public ?Collection $history = null, + public ?EventCollection $history = null, ) { - $this->history ??= (new MachineEvent())->newCollection(); + $this->history ??= new EventCollection(); $this->updateMachineValueFromState(); } diff --git a/src/EventCollection.php b/src/EventCollection.php new file mode 100644 index 0000000..d5d035e --- /dev/null +++ b/src/EventCollection.php @@ -0,0 +1,11 @@ + Date: Mon, 4 Dec 2023 22:45:23 +0300 Subject: [PATCH 08/33] feat: Inject `EventCollection` into `runAction` in `MachineDefinition.php` (WEB-4344) This commit modifies the `runAction` method in `src/Definition/MachineDefinition.php` to include `EventCollection` as a parameter. It also updates the test `it can inject requested parameters` in `tests/BehaviorDependencyInjectionTest.php` to pass `EventCollection` and adds assertions to check the instance and count of `EventCollection`. --- src/Definition/MachineDefinition.php | 13 ++++++++----- tests/BehaviorDependencyInjectionTest.php | 5 +++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index dc6eebd..fd8b8b9 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -8,6 +8,7 @@ use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; +use Tarfinlabs\EventMachine\EventCollection; use Tarfinlabs\EventMachine\Enums\BehaviorType; use Tarfinlabs\EventMachine\Enums\InternalEvent; use Tarfinlabs\EventMachine\Behavior\EventBehavior; @@ -689,6 +690,8 @@ public function transition( * * @param string $actionDefinition The action definition, either a class * @param EventBehavior|null $eventBehavior The event (optional). + * + * @throws \ReflectionException */ public function runAction( string $actionDefinition, @@ -726,13 +729,13 @@ public function runAction( $numberOfEventsInQueue = $this->eventQueue->count(); $actionBehaviorParameters = []; - /** @var \ReflectionParameter $parameter */ foreach ((new ReflectionFunction($actionBehavior))->getParameters() as $parameter) { $value = match ($parameter->getType()->getName()) { - ContextManager::class => $state->context, - EventBehavior::class => $eventBehavior, - State::class => $state, - default => null, + ContextManager::class => $state->context, + EventBehavior::class => $eventBehavior, + State::class => $state, + EventCollection::class => $state->history, + default => null, }; $actionBehaviorParameters[$parameter->getName()] = $value; } diff --git a/tests/BehaviorDependencyInjectionTest.php b/tests/BehaviorDependencyInjectionTest.php index 78f58c9..6874af9 100644 --- a/tests/BehaviorDependencyInjectionTest.php +++ b/tests/BehaviorDependencyInjectionTest.php @@ -5,6 +5,7 @@ use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\Actor\Machine; use Tarfinlabs\EventMachine\ContextManager; +use Tarfinlabs\EventMachine\EventCollection; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Definition\MachineDefinition; @@ -29,6 +30,7 @@ ContextManager $c, EventBehavior $e, State $s, + EventCollection $ec ): void { expect($c)->toBeInstanceOf(ContextManager::class); expect($c->value)->toBe(1); @@ -38,6 +40,9 @@ expect($s)->toBeInstanceOf(State::class); expect($s->value)->toBe(['machine.ready']); + + expect($ec)->toBeInstanceOf(EventCollection::class); + expect($ec->count())->toBe(7); }, ], ], From 085df2921b3f0c9f6ae2e44b4ba80910ea4b0121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 22:47:21 +0300 Subject: [PATCH 09/33] chore: Update .gitignore (WEB-4344) --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a7f372d..e26945a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ phpstan.neon testbench.yaml vendor node_modules +.DS_Store From b9c9b6d6cd205768b585a499a1fbd23f673c4ddd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:15:58 +0300 Subject: [PATCH 10/33] feat: Enhance parameter type handling in `runAction` method (WEB-4344) This commit modifies the `runAction` method in `src/Definition/MachineDefinition.php` to handle parameters with union types. It also adjusts the reflection process to accommodate `InvokableBehavior` instances. The changes allow the method to correctly determine the type of each parameter and assign the appropriate value. --- src/Definition/MachineDefinition.php | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index fd8b8b9..2644ee8 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -4,7 +4,9 @@ namespace Tarfinlabs\EventMachine\Definition; +use ReflectionMethod; use ReflectionFunction; +use ReflectionUnionType; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; @@ -729,8 +731,17 @@ public function runAction( $numberOfEventsInQueue = $this->eventQueue->count(); $actionBehaviorParameters = []; - foreach ((new ReflectionFunction($actionBehavior))->getParameters() as $parameter) { - $value = match ($parameter->getType()->getName()) { + + $reflectionFunction = $actionBehavior instanceof InvokableBehavior + ? new ReflectionMethod($actionBehavior, '__invoke') + : new ReflectionFunction($actionBehavior); + + foreach ($reflectionFunction->getParameters() as $parameter) { + $parameterTypeName = $parameter->getType() instanceof ReflectionUnionType + ? $parameter->getType()->getTypes()[0]->getName() + : $parameter->getType()->getName(); + + $value = match ($parameterTypeName) { ContextManager::class => $state->context, EventBehavior::class => $eventBehavior, State::class => $state, From 8b6e4256cdfa4628d6762c195b91559c98dc8dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:23:51 +0300 Subject: [PATCH 11/33] refactor: Change parent class of `EventCollection` to `Illuminate\Database\Eloquent\Collection` (WEB-4344) This commit modifies the `EventCollection` class in `src/EventCollection.php`. The parent class has been changed from `Illuminate\Support\Collection` to `Illuminate\Database\Eloquent\Collection`. --- src/EventCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/EventCollection.php b/src/EventCollection.php index d5d035e..23d178e 100644 --- a/src/EventCollection.php +++ b/src/EventCollection.php @@ -4,7 +4,7 @@ namespace Tarfinlabs\EventMachine; -use Illuminate\Support\Collection; +use Illuminate\Database\Eloquent\Collection; class EventCollection extends Collection { From c5fd6337099b5892b964869112b0d096409f757a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:24:47 +0300 Subject: [PATCH 12/33] feat: Override `newCollection` method in `MachineEvent.php` (WEB-4344) This commit adds a `newCollection` method to the `MachineEvent` model in `src/Models/MachineEvent.php`. This method overrides the default Eloquent collection with a custom `EventCollection`. This allows for additional methods to be available on the collection of `MachineEvent` models. --- src/Models/MachineEvent.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Models/MachineEvent.php b/src/Models/MachineEvent.php index d5ca53f..3c6ad86 100644 --- a/src/Models/MachineEvent.php +++ b/src/Models/MachineEvent.php @@ -6,6 +6,7 @@ use Illuminate\Support\Carbon; use Illuminate\Database\Eloquent\Model; +use Tarfinlabs\EventMachine\EventCollection; use Tarfinlabs\EventMachine\Enums\SourceType; use Illuminate\Database\Eloquent\Concerns\HasUlids; use Illuminate\Database\Eloquent\Factories\HasFactory; @@ -77,4 +78,20 @@ protected static function newFactory(): MachineEventFactory { return MachineEventFactory::new(); } + + /** + * Create a new collection of models. + * + * This method overrides the default Eloquent collection with a custom + * EventCollection. This allows for additional methods to be available + * on the collection of MachineEvent models. + * + * @param array $models An array of MachineEvent models. + * + * @return EventCollection A new instance of EventCollection. + */ + public function newCollection(array $models = []): EventCollection + { + return new EventCollection($models); + } } From daffe6b278fc9df8678a18dc0807a41d2b2a4a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:28:18 +0300 Subject: [PATCH 13/33] test: Replace `EventDefinition` with `EventBehavior` in action methods (WEB-4344) This commit updates the action methods in `tests/EventStoreTest.php` and `tests/ActionTest.php`. The `EventDefinition` parameter has been replaced with `EventBehavior` in the `additionAction` and `subtractionAction` methods. This change aligns the parameter type with the actual type of event being passed to these methods. --- tests/ActionTest.php | 8 ++++---- tests/EventStoreTest.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ActionTest.php b/tests/ActionTest.php index e642de6..d3b0128 100644 --- a/tests/ActionTest.php +++ b/tests/ActionTest.php @@ -29,11 +29,11 @@ ], behavior: [ 'actions' => [ - 'additionAction' => function (ContextManager $context, EventDefinition $eventDefinition): void { - $context->set('count', $context->get('count') + $eventDefinition->payload['value']); + 'additionAction' => function (ContextManager $context, EventBehavior $eventBehavior): void { + $context->set('count', $context->get('count') + $eventBehavior->payload['value']); }, - 'subtractionAction' => function (ContextManager $context, EventDefinition $eventDefinition): void { - $context->set('count', $context->get('count') - $eventDefinition->payload['value']); + 'subtractionAction' => function (ContextManager $context, EventBehavior $eventBehavior): void { + $context->set('count', $context->get('count') - $eventBehavior->payload['value']); }, 'incrementAction' => function (ContextManager $context): void { $context->set('count', $context->get('count') + 1); diff --git a/tests/EventStoreTest.php b/tests/EventStoreTest.php index d916fc8..e4e83d1 100644 --- a/tests/EventStoreTest.php +++ b/tests/EventStoreTest.php @@ -3,7 +3,7 @@ declare(strict_types=1); use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Definition\EventDefinition; +use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Definition\MachineDefinition; it('stores external events', function (): void { @@ -80,8 +80,8 @@ ], behavior: [ 'actions' => [ - 'additionAction' => function (ContextManager $context, EventDefinition $eventDefinition): void { - $context->set('count', $context->get('count') + $eventDefinition->payload['value']); + 'additionAction' => function (ContextManager $context, EventBehavior $eventBehavior): void { + $context->set('count', $context->get('count') + $eventBehavior->payload['value']); }, ], ] From a78ccd5344e417d1c8aec550fffe4691234a17e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:39:00 +0300 Subject: [PATCH 14/33] refactor: Improve parameter type handling in `runAction` method (WEB-4344) This commit refactors the `runAction` method in `src/Definition/MachineDefinition.php` to improve how it handles parameter types. Instead of matching the parameter type name, it now checks if the parameter type is an instance of the expected classes (`ContextManager`, `EventBehavior`, `State`, `EventCollection`). --- src/Definition/MachineDefinition.php | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 2644ee8..f213eb8 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -10,7 +10,6 @@ use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\EventCollection; use Tarfinlabs\EventMachine\Enums\BehaviorType; use Tarfinlabs\EventMachine\Enums\InternalEvent; use Tarfinlabs\EventMachine\Behavior\EventBehavior; @@ -737,17 +736,20 @@ public function runAction( : new ReflectionFunction($actionBehavior); foreach ($reflectionFunction->getParameters() as $parameter) { - $parameterTypeName = $parameter->getType() instanceof ReflectionUnionType - ? $parameter->getType()->getTypes()[0]->getName() - : $parameter->getType()->getName(); - - $value = match ($parameterTypeName) { - ContextManager::class => $state->context, - EventBehavior::class => $eventBehavior, - State::class => $state, - EventCollection::class => $state->history, - default => null, + $parameterType = $parameter->getType(); + + $typeName = $parameterType instanceof ReflectionUnionType + ? $parameterType->getTypes()[0]->getName() + : $parameterType->getName(); + + $value = match (true) { + is_a($state->context, $typeName) => $state->context, // ContextManager + is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior + is_a($state, $typeName) => $state, // State + is_a($state->history, $typeName) => $state->history, // EventCollection + default => null, }; + $actionBehaviorParameters[$parameter->getName()] = $value; } From d4e4356883417bfabb57133539506e7dd4ca031d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:46:27 +0300 Subject: [PATCH 15/33] feat(MachineDefinition): refactor action behavior parameter assignment (WEB-4344) Refactor the assignment of action behavior parameters in `MachineDefinition.php` commit. Instead of assigning each parameter individually, an array of parameters is now used. --- src/Definition/MachineDefinition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index f213eb8..882ba04 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -750,7 +750,7 @@ public function runAction( default => null, }; - $actionBehaviorParameters[$parameter->getName()] = $value; + $actionBehaviorParameters[] = $value; } // Execute the action behavior. From eb6a90073cc778561a55d8d91b0ae696a6bf31da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:47:07 +0300 Subject: [PATCH 16/33] refactor(MachineDefinition): improve parameter assignment in commit (WEB-4344) Improve parameter assignment in `MachineDefinition.php` commit. Instead of assigning parameters individually, utilize an array for action behavior arguments when `$typeName` is 'array'. --- src/Definition/MachineDefinition.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 882ba04..515e730 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -747,6 +747,7 @@ public function runAction( is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior is_a($state, $typeName) => $state, // State is_a($state->history, $typeName) => $state->history, // EventCollection + $typeName === 'array' => $actionArguments, // Behavior Arguments default => null, }; From 4802a694218ef7be7e612cd6529ff0a5f9fb93cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Mon, 4 Dec 2023 23:47:35 +0300 Subject: [PATCH 17/33] test(InvokableBehaviorArgumentsTest): update argument variable names in `additionAction()` (WEB-4344) Update argument variable names in the `additionAction` function in `InvokableBehaviorArgumentsTest.php` commit. Rename `ContextManager $context` to `$ctx`, `EventDefinition $eventDefinition` to `$ed`, and `array $arguments` to `$arguments`. --- tests/InvokableBehaviorArgumentsTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/InvokableBehaviorArgumentsTest.php b/tests/InvokableBehaviorArgumentsTest.php index 4e46df4..96298dc 100644 --- a/tests/InvokableBehaviorArgumentsTest.php +++ b/tests/InvokableBehaviorArgumentsTest.php @@ -25,8 +25,8 @@ ], behavior: [ 'actions' => [ - 'additionAction' => function (ContextManager $context, EventDefinition $eventDefinition, array $arguments = null): void { - $context->count += array_sum($arguments); + 'additionAction' => function (ContextManager $ctx, EventDefinition $ed, array $arguments = null): void { + $ctx->count += array_sum($arguments); }, ], ], From f07c8a6aa739e82435967c58842d09e9f2c170b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:51:57 +0300 Subject: [PATCH 18/33] refactor: Update `__invoke()` to `definition()` in behaviors and guards (WEB-4344) In this commit, the `__invoke()` method in various behavior and guard classes within the EventMachine framework is replaced by the `definition()` method returning a `Closure`. This change affects multiple files, including `ActionBehavior`, `GuardBehavior`, `ResultBehavior`, and several specific action and guard implementations in tests. The refactor streamlines the invocation process and enhances the flexibility in defining behavior and guard logic. Specifically, it allows the encapsulation of the logic within a `Closure`, providing a more concise and manageable approach. This change is a significant shift in the method of defining behaviors and guards, moving towards a more functional style of programming within the framework. --- src/Behavior/ActionBehavior.php | 15 ++++----------- src/Behavior/GuardBehavior.php | 16 +++++----------- src/Behavior/InvokableBehavior.php | 20 +++++++++----------- src/Behavior/ResultBehavior.php | 11 ++++------- src/Behavior/ValidationGuardBehavior.php | 17 ----------------- 5 files changed, 22 insertions(+), 57 deletions(-) diff --git a/src/Behavior/ActionBehavior.php b/src/Behavior/ActionBehavior.php index d47a429..c6769e9 100644 --- a/src/Behavior/ActionBehavior.php +++ b/src/Behavior/ActionBehavior.php @@ -4,8 +4,6 @@ namespace Tarfinlabs\EventMachine\Behavior; -use Tarfinlabs\EventMachine\ContextManager; - /** * ActionBehavior class. * @@ -16,14 +14,9 @@ abstract class ActionBehavior extends InvokableBehavior { /** * Invokes the method with the given parameters. - * - * @param ContextManager $context Provides access to the context in which the method is being invoked. - * @param EventBehavior $eventBehavior The event behavior associated with the method invocation. - * @param array|null $arguments Optional parameters to be passed to the method. */ - abstract public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ): void; + public function __invoke(): void + { + parent::__invoke(); + } } diff --git a/src/Behavior/GuardBehavior.php b/src/Behavior/GuardBehavior.php index f3f6024..1279869 100644 --- a/src/Behavior/GuardBehavior.php +++ b/src/Behavior/GuardBehavior.php @@ -4,8 +4,6 @@ namespace Tarfinlabs\EventMachine\Behavior; -use Tarfinlabs\EventMachine\ContextManager; - /** * Class GuardBehavior. * @@ -17,15 +15,11 @@ abstract class GuardBehavior extends InvokableBehavior /** * Invokes the method. * - * @param ContextManager $context The context manager. - * @param EventBehavior $eventBehavior The event behavior. - * @param array|null $arguments The optional arguments for the method. * - * @return bool Returns true if the method is invoked successfully, false otherwise. + * @return bool Returns true if the method invocation was successful, false otherwise. */ - abstract public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ): bool; + public function __invoke(): bool + { + return parent::__invoke(); + } } diff --git a/src/Behavior/InvokableBehavior.php b/src/Behavior/InvokableBehavior.php index 3513fa8..4ff324d 100644 --- a/src/Behavior/InvokableBehavior.php +++ b/src/Behavior/InvokableBehavior.php @@ -4,6 +4,7 @@ namespace Tarfinlabs\EventMachine\Behavior; +use Closure; use Illuminate\Support\Str; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\ContextManager; @@ -38,24 +39,21 @@ public function __construct( } } + abstract public function definition(): Closure; + /** * Executes the behavior with the given context and event. * * This method defines the contract for implementing behaviors * within classes. The behavior should be directly invokable by * passing in a ContextManager instance and an array of event payload. - * - * @param ContextManager $context The context to be used during - * invocation. - * @param \Tarfinlabs\EventMachine\Behavior\EventBehavior $eventBehavior The event related to the - * current behavior. - * @param array|null $arguments The arguments to be passed to the behavior. */ - abstract public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ); + public function __invoke() + { + $closure = $this->definition(); + + return $closure(); + } /** * Raises an event by adding it to the event queue. diff --git a/src/Behavior/ResultBehavior.php b/src/Behavior/ResultBehavior.php index c80a68f..02d2ba6 100644 --- a/src/Behavior/ResultBehavior.php +++ b/src/Behavior/ResultBehavior.php @@ -4,13 +4,10 @@ namespace Tarfinlabs\EventMachine\Behavior; -use Tarfinlabs\EventMachine\ContextManager; - abstract class ResultBehavior extends InvokableBehavior { - abstract public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ): mixed; + public function __invoke(): mixed + { + return parent::__invoke(); + } } diff --git a/src/Behavior/ValidationGuardBehavior.php b/src/Behavior/ValidationGuardBehavior.php index 439c2bd..64cabe6 100644 --- a/src/Behavior/ValidationGuardBehavior.php +++ b/src/Behavior/ValidationGuardBehavior.php @@ -4,8 +4,6 @@ namespace Tarfinlabs\EventMachine\Behavior; -use Tarfinlabs\EventMachine\ContextManager; - /** * An abstract class that represents a validation guard behavior. * @@ -18,19 +16,4 @@ abstract class ValidationGuardBehavior extends GuardBehavior { /** @var string|null Holds an error message, which is initially null. */ public ?string $errorMessage = null; - - /** - * Invokes the method. - * - * @param ContextManager $context The context manager. - * @param EventBehavior $eventBehavior The event behavior. - * @param array|null $arguments The arguments for the method (optional). - * - * @return bool Returns true if the method invocation was successful, false otherwise. - */ - abstract public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ): bool; } From a3592ffd1232e3e4ff04e6c5d8e77a57ecd2e251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:52:45 +0300 Subject: [PATCH 19/33] test: Fix Actions (WEB-4344) --- tests/ActionTest.php | 14 ++++++-------- tests/Stubs/Actions/IsOddAction.php | 8 +++++--- tests/Stubs/Machines/Asd/Actions/AAction.php | 13 +++++++------ tests/Stubs/Machines/Asd/Actions/DAction.php | 13 ++++++------- tests/Stubs/Machines/Asd/Actions/SAction.php | 16 +++++++--------- tests/Stubs/Machines/Asd/Actions/SleepAction.php | 12 +++++------- tests/Stubs/Machines/Qwerty/Actions/TAction.php | 10 ++++++++-- .../Actions/AddAnotherValueAction.php | 12 ++++++++---- .../TrafficLights/Actions/AddValueAction.php | 12 ++++++++---- .../TrafficLights/Actions/DecrementAction.php | 15 ++++++--------- .../Actions/DoNothingInsideClassAction.php | 8 ++++---- .../TrafficLights/Actions/IncrementAction.php | 10 +++++----- .../Actions/MultiplyByTwoAction.php | 10 +++++----- .../Actions/SubtractValueAction.php | 12 ++++++++---- tests/Stubs/Machines/Xyz/Actions/XAction.php | 15 +++++++-------- tests/Stubs/Machines/Xyz/Actions/YAction.php | 15 +++++++-------- tests/Stubs/Machines/Xyz/Actions/ZAction.php | 15 +++++++-------- tests/Stubs/Results/GreenResult.php | 14 ++++++-------- 18 files changed, 115 insertions(+), 109 deletions(-) diff --git a/tests/ActionTest.php b/tests/ActionTest.php index d3b0128..17b708c 100644 --- a/tests/ActionTest.php +++ b/tests/ActionTest.php @@ -92,18 +92,16 @@ $value = random_int(10, 20); $multipleWithItselfAction = new class extends ResultBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): int { - return $eventBehavior->payload['value'] * $eventBehavior->payload['value']; + public function definition(): Closure + { + return function (EventBehavior $eventBehavior): int { + return $eventBehavior->payload['value'] * $eventBehavior->payload['value']; + }; } }; // 2. Act - $result = $multipleWithItselfAction( - context: new ContextManager(), + $result = $multipleWithItselfAction->definition()( eventBehavior: EventDefinition::from([ 'type' => 'ADD', 'payload' => [ diff --git a/tests/Stubs/Actions/IsOddAction.php b/tests/Stubs/Actions/IsOddAction.php index 1c9041a..6d989db 100644 --- a/tests/Stubs/Actions/IsOddAction.php +++ b/tests/Stubs/Actions/IsOddAction.php @@ -4,8 +4,8 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Actions; +use Closure; use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class IsOddAction extends ActionBehavior @@ -14,8 +14,10 @@ class IsOddAction extends ActionBehavior 'counts.oddCount' => 'integer', ]; - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - $context->set('counts.oddCount', 1); + return function (ContextManager $context): void { + $context->set('counts.oddCount', 1); + }; } } diff --git a/tests/Stubs/Machines/Asd/Actions/AAction.php b/tests/Stubs/Machines/Asd/Actions/AAction.php index 1515e78..0929a4c 100644 --- a/tests/Stubs/Machines/Asd/Actions/AAction.php +++ b/tests/Stubs/Machines/Asd/Actions/AAction.php @@ -4,17 +4,18 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Models\ModelA; class AAction extends ActionBehavior { - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - ModelA::create([ - 'value' => 'lorem ipsum dolor', - ]); + return function (): void { + ModelA::create([ + 'value' => 'lorem ipsum dolor', + ]); + }; } } diff --git a/tests/Stubs/Machines/Asd/Actions/DAction.php b/tests/Stubs/Machines/Asd/Actions/DAction.php index 9b12bd3..0f2eb8e 100644 --- a/tests/Stubs/Machines/Asd/Actions/DAction.php +++ b/tests/Stubs/Machines/Asd/Actions/DAction.php @@ -4,17 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; +use Exception; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class DAction extends ActionBehavior { - /** - * @throws \Exception - */ - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - throw new \Exception('error'); + return function (): void { + throw new Exception('error'); + }; } } diff --git a/tests/Stubs/Machines/Asd/Actions/SAction.php b/tests/Stubs/Machines/Asd/Actions/SAction.php index 79421dc..e4952a8 100644 --- a/tests/Stubs/Machines/Asd/Actions/SAction.php +++ b/tests/Stubs/Machines/Asd/Actions/SAction.php @@ -4,20 +4,18 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Models\ModelA; class SAction extends ActionBehavior { - /** - * @throws \Exception - */ - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - ModelA::first()->update([ - 'value' => 'new value', - ]); + return function (): void { + ModelA::first()->update([ + 'value' => 'new value', + ]); + }; } } diff --git a/tests/Stubs/Machines/Asd/Actions/SleepAction.php b/tests/Stubs/Machines/Asd/Actions/SleepAction.php index 0cfaf38..d75a8a2 100644 --- a/tests/Stubs/Machines/Asd/Actions/SleepAction.php +++ b/tests/Stubs/Machines/Asd/Actions/SleepAction.php @@ -4,17 +4,15 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class SleepAction extends ActionBehavior { - /** - * @throws \Exception - */ - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - sleep(1); + return function (): void { + sleep(1); + }; } } diff --git a/tests/Stubs/Machines/Qwerty/Actions/TAction.php b/tests/Stubs/Machines/Qwerty/Actions/TAction.php index 48456d9..cf04071 100644 --- a/tests/Stubs/Machines/Qwerty/Actions/TAction.php +++ b/tests/Stubs/Machines/Qwerty/Actions/TAction.php @@ -4,6 +4,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Qwerty\Actions; +use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; @@ -11,8 +12,13 @@ class TAction extends ActionBehavior { - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - $this->raise(new TEvent(actor: $eventBehavior->actor($context))); + return function ( + ContextManager $context, + EventBehavior $eventBehavior + ): void { + $this->raise(new TEvent(actor: $eventBehavior->actor($context))); + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php index 0b39508..3eff912 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php @@ -4,16 +4,20 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Events\AddAnotherValueEvent; class AddAnotherValueAction extends ActionBehavior { - public function __invoke(ContextManager|TrafficLightsContext $context, EventBehavior|AddAnotherValueEvent $eventBehavior, array $arguments = null): void + public function definition(): Closure { - $context->count += $eventBehavior->value; + return function ( + TrafficLightsContext $context, + AddAnotherValueEvent $eventBehavior + ): void { + $context->count += $eventBehavior->value; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php index 386c27a..e735b48 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php @@ -4,16 +4,20 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; +use Closure; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class AddValueAction extends ActionBehavior { - public function __invoke(ContextManager|TrafficLightsContext $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - /* @var \Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext $context */ - $context->count += $eventBehavior->payload['value']; + return function ( + TrafficLightsContext $context, + EventBehavior $eventBehavior + ): void { + $context->count += $eventBehavior->payload['value']; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php b/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php index 6ee6407..91c1453 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php @@ -4,19 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class DecrementAction extends ActionBehavior { - public function __invoke( - ContextManager|TrafficLightsContext $context, - EventBehavior $eventBehavior, - array $arguments = null - ): void { - /* @var \Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext $context */ - $context->count--; + public function definition(): Closure + { + return function (TrafficLightsContext $context): void { + $context->count--; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php b/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php index c2066d5..12a4250 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php @@ -4,14 +4,14 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class DoNothingInsideClassAction extends ActionBehavior { - public function __invoke(ContextManager $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - // Do nothing. + return function (): void { + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php b/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php index 6f69df3..e549110 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php @@ -4,16 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class IncrementAction extends ActionBehavior { - public function __invoke(ContextManager|TrafficLightsContext $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - /* @var \Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext $context */ - $context->count++; + return function (TrafficLightsContext $context): void { + $context->count++; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php b/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php index 1367e67..0d1c5ca 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php @@ -4,8 +4,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -13,9 +12,10 @@ class MultiplyByTwoAction extends ActionBehavior { public bool $shouldLog = true; - public function __invoke(ContextManager|TrafficLightsContext $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - /* @var \Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext $context */ - $context->count *= 2; + return function (TrafficLightsContext $context): void { + $context->count *= 2; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php index 8139c9e..b0ab408 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php @@ -4,16 +4,20 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Tarfinlabs\EventMachine\ContextManager; +use Closure; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class SubtractValueAction extends ActionBehavior { - public function __invoke(ContextManager|TrafficLightsContext $context, EventBehavior $eventBehavior, array $arguments = null): void + public function definition(): Closure { - /* @var \Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext $context */ - $context->count -= $eventBehavior->payload['value']; + return function ( + TrafficLightsContext $context, + EventBehavior $eventBehavior + ): void { + $context->count -= $eventBehavior->payload['value']; + }; } } diff --git a/tests/Stubs/Machines/Xyz/Actions/XAction.php b/tests/Stubs/Machines/Xyz/Actions/XAction.php index 09e53e3..fbecd1b 100644 --- a/tests/Stubs/Machines/Xyz/Actions/XAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/XAction.php @@ -4,19 +4,18 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; +use Closure; use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class XAction extends ActionBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): void { - $context->value .= 'x'; + public function definition(): Closure + { + return function (ContextManager $context): void { + $context->value .= 'x'; - $this->raise(['type' => '@x']); + $this->raise(['type' => '@x']); + }; } } diff --git a/tests/Stubs/Machines/Xyz/Actions/YAction.php b/tests/Stubs/Machines/Xyz/Actions/YAction.php index 3b172bd..7fcdcb5 100644 --- a/tests/Stubs/Machines/Xyz/Actions/YAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/YAction.php @@ -4,20 +4,19 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; +use Closure; use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Events\YEvent; class YAction extends ActionBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): void { - $context->value .= 'y'; + public function definition(): Closure + { + return function (ContextManager $context): void { + $context->value .= 'y'; - $this->raise(new YEvent()); + $this->raise(new YEvent()); + }; } } diff --git a/tests/Stubs/Machines/Xyz/Actions/ZAction.php b/tests/Stubs/Machines/Xyz/Actions/ZAction.php index 698f0e2..1b5fc23 100644 --- a/tests/Stubs/Machines/Xyz/Actions/ZAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/ZAction.php @@ -4,19 +4,18 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; +use Closure; use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class ZAction extends ActionBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): void { - $context->value .= 'z'; + public function definition(): Closure + { + return function (ContextManager $context): void { + $context->value .= 'z'; - $this->raise(['type' => '@z']); + $this->raise(['type' => '@z']); + }; } } diff --git a/tests/Stubs/Results/GreenResult.php b/tests/Stubs/Results/GreenResult.php index 40d67ce..e9145dc 100644 --- a/tests/Stubs/Results/GreenResult.php +++ b/tests/Stubs/Results/GreenResult.php @@ -4,18 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Results; +use Closure; use Illuminate\Support\Carbon; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ResultBehavior; class GreenResult extends ResultBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): Carbon { - return now(); + public function definition(): Closure + { + return function (): Carbon { + return now(); + }; } } From 6d537715674405733f0fb050cb643627d7a92e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:53:43 +0300 Subject: [PATCH 20/33] refactor: Update how `runAction` method handles `InvokableBehavior` in `MachineDefinition.php` (WEB-4344) This commit modifies the `runAction` method in `src/Definition/MachineDefinition.php`. The way `InvokableBehavior` instances are handled has been updated. Instead of using a `ReflectionMethod` to get the parameters of the `__invoke` method, a `ReflectionFunction` is now used on the result of the `definition()` method. The action behavior is then executed by invoking the `definition()` method directly if the behavior is an instance of `InvokableBehavior`, or the behavior itself otherwise. --- src/Definition/MachineDefinition.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 515e730..38e9a97 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Definition; -use ReflectionMethod; use ReflectionFunction; use ReflectionUnionType; use Illuminate\Support\Collection; @@ -732,7 +731,7 @@ public function runAction( $actionBehaviorParameters = []; $reflectionFunction = $actionBehavior instanceof InvokableBehavior - ? new ReflectionMethod($actionBehavior, '__invoke') + ? new ReflectionFunction($actionBehavior->definition()) : new ReflectionFunction($actionBehavior); foreach ($reflectionFunction->getParameters() as $parameter) { @@ -755,7 +754,10 @@ public function runAction( } // Execute the action behavior. - $actionBehavior(...$actionBehaviorParameters); + ($actionBehavior instanceof InvokableBehavior + ? $actionBehavior->definition() + : $actionBehavior + )(...$actionBehaviorParameters); // Get the number of events in the queue after the action is executed. $newNumberOfEventsInQueue = $this->eventQueue->count(); From d8eb1cb48b5d28cf15f80f90728fe1fcf38d1b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:54:25 +0300 Subject: [PATCH 21/33] refactor: Enhance guard behavior handling in `getFirstValidTransitionBranch` method (WEB-4344) This commit modifies the `getFirstValidTransitionBranch` method in `src/Definition/TransitionDefinition.php`. The method now supports `InvokableBehavior` instances for guard behaviors. It uses reflection to determine the parameters of the guard behavior and passes the appropriate arguments based on the parameter types. This change allows for more flexible guard behaviors in transition definitions. --- src/Definition/TransitionDefinition.php | 37 ++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/Definition/TransitionDefinition.php b/src/Definition/TransitionDefinition.php index 57817db..c799526 100644 --- a/src/Definition/TransitionDefinition.php +++ b/src/Definition/TransitionDefinition.php @@ -4,12 +4,15 @@ namespace Tarfinlabs\EventMachine\Definition; +use ReflectionFunction; +use ReflectionUnionType; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\Enums\BehaviorType; use Tarfinlabs\EventMachine\Enums\InternalEvent; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\GuardBehavior; use Tarfinlabs\EventMachine\Enums\TransitionProperty; +use Tarfinlabs\EventMachine\Behavior\InvokableBehavior; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; /** @@ -135,6 +138,8 @@ protected function isAMultiPathGuardedTransition(null|array|string $transitionCo * * @return TransitionDefinition|null The first eligible transition or * null if no eligible transition is found. + * + * @throws \ReflectionException */ public function getFirstValidTransitionBranch( EventBehavior $eventBehavior, @@ -169,7 +174,37 @@ public function getFirstValidTransitionBranch( $guardBehavior->validateRequiredContext($state->context); } - if ($guardBehavior($state->context, $eventBehavior, $guardArguments) === false) { + $guardBehaviorParameters = []; + + $reflectionFunction = $guardBehavior instanceof InvokableBehavior + ? new ReflectionFunction($guardBehavior->definition()) + : new ReflectionFunction($guardBehavior); + + foreach ($reflectionFunction->getParameters() as $parameter) { + $parameterType = $parameter->getType(); + + $typeName = $parameterType instanceof ReflectionUnionType + ? $parameterType->getTypes()[0]->getName() + : $parameterType->getName(); + + $value = match (true) { + is_a($state->context, $typeName) => $state->context, // ContextManager + is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior + is_a($state, $typeName) => $state, // State + is_a($state->history, $typeName) => $state->history, // EventCollection + $typeName === 'array' => $guardArguments, // Behavior Arguments + default => null, + }; + + $guardBehaviorParameters[] = $value; + } + + $guardResult = ($guardBehavior instanceof InvokableBehavior + ? $guardBehavior->definition() + : $guardBehavior + )(...$guardBehaviorParameters); + + if ($guardResult === false) { $guardsPassed = false; $payload = null; From bc055c0584f41a8ad6a2a7a0547d0a403af90d75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:54:29 +0300 Subject: [PATCH 22/33] test: Fix guards (WEB-4344) --- .../Guards/IsTimerValidValidationGuard.php | 26 +++++++++++-------- tests/Stubs/Guards/IsValidatedOddGuard.php | 14 +++++----- .../TrafficLights/Guards/IsEvenGuard.php | 14 +++++----- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/Stubs/Guards/IsTimerValidValidationGuard.php b/tests/Stubs/Guards/IsTimerValidValidationGuard.php index f6195c6..5d77d84 100644 --- a/tests/Stubs/Guards/IsTimerValidValidationGuard.php +++ b/tests/Stubs/Guards/IsTimerValidValidationGuard.php @@ -4,24 +4,28 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; +use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; class IsTimerValidValidationGuard extends ValidationGuardBehavior { - public function __invoke( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): bool { - $value = $eventBehavior->payload['value']; - $result = $value > (int) $arguments[0]; + public function definition(): Closure + { + return function ( + ContextManager $context, + EventBehavior $eventBehavior, + array $arguments = null, + ) { + $value = $eventBehavior->payload['value']; + $result = $value > (int) $arguments[0]; - if ($result === false) { - $this->errorMessage = "Timer has a value of {$value}, must be greater than {$arguments[0]}."; - } + if ($result === false) { + $this->errorMessage = "Timer has a value of {$value}, must be greater than {$arguments[0]}."; + } - return $result; + return $result; + }; } } diff --git a/tests/Stubs/Guards/IsValidatedOddGuard.php b/tests/Stubs/Guards/IsValidatedOddGuard.php index 69df16b..22f11c6 100644 --- a/tests/Stubs/Guards/IsValidatedOddGuard.php +++ b/tests/Stubs/Guards/IsValidatedOddGuard.php @@ -4,8 +4,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -16,11 +15,10 @@ class IsValidatedOddGuard extends ValidationGuardBehavior ]; public ?string $errorMessage = 'Count is not odd'; - public function __invoke( - TrafficLightsContext|ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): bool { - return $context->count % 2 === 1; + public function definition(): Closure + { + return function (TrafficLightsContext $context) { + return $context->count % 2 === 1; + }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php b/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php index aa2acc0..f5e9d22 100644 --- a/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php +++ b/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php @@ -4,8 +4,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Guards; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -14,11 +13,10 @@ class IsEvenGuard extends ValidationGuardBehavior public ?string $errorMessage = 'Count is not even'; public bool $shouldLog = true; - public function __invoke( - ContextManager|TrafficLightsContext $context, - EventBehavior $eventBehavior, - array $arguments = null - ): bool { - return $context->count % 2 === 0; + public function definition(): Closure + { + return function (TrafficLightsContext $context): bool { + return $context->count % 2 === 0; + }; } } From bf66715227486695b688d5cedf73006b1c328f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 01:58:48 +0300 Subject: [PATCH 23/33] test: fix (WEB-4344) --- tests/Stubs/Guards/IsOddGuard.php | 14 ++++++-------- tests/Stubs/Machines/Asd/Actions/DAction.php | 4 ++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/tests/Stubs/Guards/IsOddGuard.php b/tests/Stubs/Guards/IsOddGuard.php index 1f04979..e9f2ba4 100644 --- a/tests/Stubs/Guards/IsOddGuard.php +++ b/tests/Stubs/Guards/IsOddGuard.php @@ -4,8 +4,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; +use Closure; use Tarfinlabs\EventMachine\Behavior\GuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -15,11 +14,10 @@ class IsOddGuard extends GuardBehavior 'counts.oddCount' => 'integer', ]; - public function __invoke( - TrafficLightsContext|ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null - ): bool { - return $context->count % 2 === 1; + public function definition(): Closure + { + return function (TrafficLightsContext $context) { + return $context->count % 2 === 1; + }; } } diff --git a/tests/Stubs/Machines/Asd/Actions/DAction.php b/tests/Stubs/Machines/Asd/Actions/DAction.php index 0f2eb8e..a90f06f 100644 --- a/tests/Stubs/Machines/Asd/Actions/DAction.php +++ b/tests/Stubs/Machines/Asd/Actions/DAction.php @@ -5,7 +5,7 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; use Closure; -use Exception; +use RuntimeException; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class DAction extends ActionBehavior @@ -13,7 +13,7 @@ class DAction extends ActionBehavior public function definition(): Closure { return function (): void { - throw new Exception('error'); + throw new RuntimeException('error'); }; } } From 48539b757b85c48642b3fea420c4b5a5f5ed7137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 18:20:16 +0300 Subject: [PATCH 24/33] WEB-4344: refactor: GuardBehavior and related classes The __invoke methods in GuardBehavior, ActionBehavior, and ResultBehavior classes have been removed as they were not adding any specific functionality. Also, the InvokableBehavior class has been simplified by removing the redundant __invoke method and the unnecessary dependency on Closure. These changes make the code simpler and easier to maintain. --- src/Behavior/ActionBehavior.php | 7 ------- src/Behavior/GuardBehavior.php | 10 ---------- src/Behavior/InvokableBehavior.php | 22 ++-------------------- src/Behavior/ResultBehavior.php | 4 ---- 4 files changed, 2 insertions(+), 41 deletions(-) diff --git a/src/Behavior/ActionBehavior.php b/src/Behavior/ActionBehavior.php index c6769e9..086181f 100644 --- a/src/Behavior/ActionBehavior.php +++ b/src/Behavior/ActionBehavior.php @@ -12,11 +12,4 @@ */ abstract class ActionBehavior extends InvokableBehavior { - /** - * Invokes the method with the given parameters. - */ - public function __invoke(): void - { - parent::__invoke(); - } } diff --git a/src/Behavior/GuardBehavior.php b/src/Behavior/GuardBehavior.php index 1279869..015f5f6 100644 --- a/src/Behavior/GuardBehavior.php +++ b/src/Behavior/GuardBehavior.php @@ -12,14 +12,4 @@ */ abstract class GuardBehavior extends InvokableBehavior { - /** - * Invokes the method. - * - * - * @return bool Returns true if the method invocation was successful, false otherwise. - */ - public function __invoke(): bool - { - return parent::__invoke(); - } } diff --git a/src/Behavior/InvokableBehavior.php b/src/Behavior/InvokableBehavior.php index 4ff324d..3e562fa 100644 --- a/src/Behavior/InvokableBehavior.php +++ b/src/Behavior/InvokableBehavior.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Behavior; -use Closure; use Illuminate\Support\Str; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\ContextManager; @@ -31,30 +30,13 @@ abstract class InvokableBehavior * * @return void */ - public function __construct( - protected ?Collection $eventQueue = null - ) { + public function __construct(protected ?Collection $eventQueue = null) + { if ($this->eventQueue === null) { $this->eventQueue = new Collection(); } } - abstract public function definition(): Closure; - - /** - * Executes the behavior with the given context and event. - * - * This method defines the contract for implementing behaviors - * within classes. The behavior should be directly invokable by - * passing in a ContextManager instance and an array of event payload. - */ - public function __invoke() - { - $closure = $this->definition(); - - return $closure(); - } - /** * Raises an event by adding it to the event queue. * diff --git a/src/Behavior/ResultBehavior.php b/src/Behavior/ResultBehavior.php index 02d2ba6..2551a83 100644 --- a/src/Behavior/ResultBehavior.php +++ b/src/Behavior/ResultBehavior.php @@ -6,8 +6,4 @@ abstract class ResultBehavior extends InvokableBehavior { - public function __invoke(): mixed - { - return parent::__invoke(); - } } From 36ebfb6e43be96e32772df20ee5e17bb4f0109bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 18:20:43 +0300 Subject: [PATCH 25/33] WEB-4344: refactor: actionBehavior and guardBehavior reflection Changed ReflectionFunction to ReflectionMethod for actionBehavior and guardBehavior. Simplified execution of both behaviors by removing unnecessary condition checks. The code is more straightforward now and this also simplifies the InvokableBehavior class. --- src/Definition/MachineDefinition.php | 12 +++++------- src/Definition/TransitionDefinition.php | 14 ++++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 38e9a97..73eb295 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -4,6 +4,7 @@ namespace Tarfinlabs\EventMachine\Definition; +use ReflectionMethod; use ReflectionFunction; use ReflectionUnionType; use Illuminate\Support\Collection; @@ -730,11 +731,11 @@ public function runAction( $actionBehaviorParameters = []; - $reflectionFunction = $actionBehavior instanceof InvokableBehavior - ? new ReflectionFunction($actionBehavior->definition()) + $actionBehaviorReflection = $actionBehavior instanceof InvokableBehavior + ? new ReflectionMethod($actionBehavior, '__invoke') : new ReflectionFunction($actionBehavior); - foreach ($reflectionFunction->getParameters() as $parameter) { + foreach ($actionBehaviorReflection->getParameters() as $parameter) { $parameterType = $parameter->getType(); $typeName = $parameterType instanceof ReflectionUnionType @@ -754,10 +755,7 @@ public function runAction( } // Execute the action behavior. - ($actionBehavior instanceof InvokableBehavior - ? $actionBehavior->definition() - : $actionBehavior - )(...$actionBehaviorParameters); + ($actionBehavior)(...$actionBehaviorParameters); // Get the number of events in the queue after the action is executed. $newNumberOfEventsInQueue = $this->eventQueue->count(); diff --git a/src/Definition/TransitionDefinition.php b/src/Definition/TransitionDefinition.php index c799526..6ab0694 100644 --- a/src/Definition/TransitionDefinition.php +++ b/src/Definition/TransitionDefinition.php @@ -4,6 +4,7 @@ namespace Tarfinlabs\EventMachine\Definition; +use ReflectionMethod; use ReflectionFunction; use ReflectionUnionType; use Tarfinlabs\EventMachine\Actor\State; @@ -176,11 +177,11 @@ public function getFirstValidTransitionBranch( $guardBehaviorParameters = []; - $reflectionFunction = $guardBehavior instanceof InvokableBehavior - ? new ReflectionFunction($guardBehavior->definition()) + $guardBehaviorReflection = $guardBehavior instanceof InvokableBehavior + ? new ReflectionMethod($guardBehavior, '__invoke') : new ReflectionFunction($guardBehavior); - foreach ($reflectionFunction->getParameters() as $parameter) { + foreach ($guardBehaviorReflection->getParameters() as $parameter) { $parameterType = $parameter->getType(); $typeName = $parameterType instanceof ReflectionUnionType @@ -192,17 +193,14 @@ public function getFirstValidTransitionBranch( is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior is_a($state, $typeName) => $state, // State is_a($state->history, $typeName) => $state->history, // EventCollection - $typeName === 'array' => $guardArguments, // Behavior Arguments + $typeName === 'array' => $guardArguments, // Behavior Arguments default => null, }; $guardBehaviorParameters[] = $value; } - $guardResult = ($guardBehavior instanceof InvokableBehavior - ? $guardBehavior->definition() - : $guardBehavior - )(...$guardBehaviorParameters); + $guardResult = ($guardBehavior)(...$guardBehaviorParameters); if ($guardResult === false) { $guardsPassed = false; From 1376841a1f78ca832c434e015f75dfaa1119571b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 18:20:56 +0300 Subject: [PATCH 26/33] WEB-4344: refactor: Replaced Closure with direct invocation in Action and Guard classes In Action and Guard classes, definitions were initialized with Closures. This change substitutes those Closures with direct imperative function calls. This approach optimizes execution, simplifies the Invokable Behavior and reduces code complexity. --- tests/Stubs/Actions/IsOddAction.php | 7 ++--- tests/Stubs/Guards/IsOddGuard.php | 7 ++--- .../Guards/IsTimerValidValidationGuard.php | 26 ++++++++----------- tests/Stubs/Guards/IsValidatedOddGuard.php | 7 ++--- tests/Stubs/Machines/Asd/Actions/AAction.php | 11 +++----- tests/Stubs/Machines/Asd/Actions/DAction.php | 7 ++--- tests/Stubs/Machines/Asd/Actions/SAction.php | 11 +++----- .../Machines/Asd/Actions/SleepAction.php | 7 ++--- .../Stubs/Machines/Qwerty/Actions/TAction.php | 14 ++++------ .../Actions/AddAnotherValueAction.php | 14 ++++------ .../TrafficLights/Actions/AddValueAction.php | 14 ++++------ .../TrafficLights/Actions/DecrementAction.php | 7 ++--- .../Actions/DoNothingInsideClassAction.php | 5 +--- .../TrafficLights/Actions/IncrementAction.php | 7 ++--- .../Actions/MultiplyByTwoAction.php | 7 ++--- .../Actions/SubtractValueAction.php | 14 ++++------ .../TrafficLights/Guards/IsEvenGuard.php | 7 ++--- tests/Stubs/Machines/Xyz/Actions/XAction.php | 9 +++---- tests/Stubs/Machines/Xyz/Actions/YAction.php | 9 +++---- tests/Stubs/Machines/Xyz/Actions/ZAction.php | 9 +++---- tests/Stubs/Results/GreenResult.php | 7 ++--- 21 files changed, 69 insertions(+), 137 deletions(-) diff --git a/tests/Stubs/Actions/IsOddAction.php b/tests/Stubs/Actions/IsOddAction.php index 6d989db..01f0cb9 100644 --- a/tests/Stubs/Actions/IsOddAction.php +++ b/tests/Stubs/Actions/IsOddAction.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Actions; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; @@ -14,10 +13,8 @@ class IsOddAction extends ActionBehavior 'counts.oddCount' => 'integer', ]; - public function definition(): Closure + public function __invoke(ContextManager $context): void { - return function (ContextManager $context): void { - $context->set('counts.oddCount', 1); - }; + $context->set('counts.oddCount', 1); } } diff --git a/tests/Stubs/Guards/IsOddGuard.php b/tests/Stubs/Guards/IsOddGuard.php index e9f2ba4..2e02dcf 100644 --- a/tests/Stubs/Guards/IsOddGuard.php +++ b/tests/Stubs/Guards/IsOddGuard.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; -use Closure; use Tarfinlabs\EventMachine\Behavior\GuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -14,10 +13,8 @@ class IsOddGuard extends GuardBehavior 'counts.oddCount' => 'integer', ]; - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): bool { - return function (TrafficLightsContext $context) { - return $context->count % 2 === 1; - }; + return $context->count % 2 === 1; } } diff --git a/tests/Stubs/Guards/IsTimerValidValidationGuard.php b/tests/Stubs/Guards/IsTimerValidValidationGuard.php index 5d77d84..6dcf44e 100644 --- a/tests/Stubs/Guards/IsTimerValidValidationGuard.php +++ b/tests/Stubs/Guards/IsTimerValidValidationGuard.php @@ -4,28 +4,24 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; class IsTimerValidValidationGuard extends ValidationGuardBehavior { - public function definition(): Closure - { - return function ( - ContextManager $context, - EventBehavior $eventBehavior, - array $arguments = null, - ) { - $value = $eventBehavior->payload['value']; - $result = $value > (int) $arguments[0]; + public function __invoke( + ContextManager $context, + EventBehavior $eventBehavior, + array $arguments = null, + ): bool { + $value = $eventBehavior->payload['value']; + $result = $value > (int) $arguments[0]; - if ($result === false) { - $this->errorMessage = "Timer has a value of {$value}, must be greater than {$arguments[0]}."; - } + if ($result === false) { + $this->errorMessage = "Timer has a value of {$value}, must be greater than {$arguments[0]}."; + } - return $result; - }; + return $result; } } diff --git a/tests/Stubs/Guards/IsValidatedOddGuard.php b/tests/Stubs/Guards/IsValidatedOddGuard.php index 22f11c6..6195657 100644 --- a/tests/Stubs/Guards/IsValidatedOddGuard.php +++ b/tests/Stubs/Guards/IsValidatedOddGuard.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Guards; -use Closure; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -15,10 +14,8 @@ class IsValidatedOddGuard extends ValidationGuardBehavior ]; public ?string $errorMessage = 'Count is not odd'; - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): bool { - return function (TrafficLightsContext $context) { - return $context->count % 2 === 1; - }; + return $context->count % 2 === 1; } } diff --git a/tests/Stubs/Machines/Asd/Actions/AAction.php b/tests/Stubs/Machines/Asd/Actions/AAction.php index 0929a4c..fa886c5 100644 --- a/tests/Stubs/Machines/Asd/Actions/AAction.php +++ b/tests/Stubs/Machines/Asd/Actions/AAction.php @@ -4,18 +4,15 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Models\ModelA; class AAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(): void { - return function (): void { - ModelA::create([ - 'value' => 'lorem ipsum dolor', - ]); - }; + ModelA::create([ + 'value' => 'lorem ipsum dolor', + ]); } } diff --git a/tests/Stubs/Machines/Asd/Actions/DAction.php b/tests/Stubs/Machines/Asd/Actions/DAction.php index a90f06f..c317a78 100644 --- a/tests/Stubs/Machines/Asd/Actions/DAction.php +++ b/tests/Stubs/Machines/Asd/Actions/DAction.php @@ -4,16 +4,13 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Closure; use RuntimeException; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class DAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(): void { - return function (): void { - throw new RuntimeException('error'); - }; + throw new RuntimeException('error'); } } diff --git a/tests/Stubs/Machines/Asd/Actions/SAction.php b/tests/Stubs/Machines/Asd/Actions/SAction.php index e4952a8..31f01b7 100644 --- a/tests/Stubs/Machines/Asd/Actions/SAction.php +++ b/tests/Stubs/Machines/Asd/Actions/SAction.php @@ -4,18 +4,15 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Models\ModelA; class SAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(): void { - return function (): void { - ModelA::first()->update([ - 'value' => 'new value', - ]); - }; + ModelA::first()->update([ + 'value' => 'new value', + ]); } } diff --git a/tests/Stubs/Machines/Asd/Actions/SleepAction.php b/tests/Stubs/Machines/Asd/Actions/SleepAction.php index d75a8a2..76b683c 100644 --- a/tests/Stubs/Machines/Asd/Actions/SleepAction.php +++ b/tests/Stubs/Machines/Asd/Actions/SleepAction.php @@ -4,15 +4,12 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Asd\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class SleepAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(): void { - return function (): void { - sleep(1); - }; + sleep(1); } } diff --git a/tests/Stubs/Machines/Qwerty/Actions/TAction.php b/tests/Stubs/Machines/Qwerty/Actions/TAction.php index cf04071..816c44e 100644 --- a/tests/Stubs/Machines/Qwerty/Actions/TAction.php +++ b/tests/Stubs/Machines/Qwerty/Actions/TAction.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Qwerty\Actions; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; @@ -12,13 +11,10 @@ class TAction extends ActionBehavior { - public function definition(): Closure - { - return function ( - ContextManager $context, - EventBehavior $eventBehavior - ): void { - $this->raise(new TEvent(actor: $eventBehavior->actor($context))); - }; + public function __invoke( + ContextManager $context, + EventBehavior $eventBehavior + ): void { + $this->raise(new TEvent(actor: $eventBehavior->actor($context))); } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php index 3eff912..424e86b 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/AddAnotherValueAction.php @@ -4,20 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Events\AddAnotherValueEvent; class AddAnotherValueAction extends ActionBehavior { - public function definition(): Closure - { - return function ( - TrafficLightsContext $context, - AddAnotherValueEvent $eventBehavior - ): void { - $context->count += $eventBehavior->value; - }; + public function __invoke( + TrafficLightsContext $context, + AddAnotherValueEvent $eventBehavior + ): void { + $context->count += $eventBehavior->value; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php index e735b48..884ebc1 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/AddValueAction.php @@ -4,20 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class AddValueAction extends ActionBehavior { - public function definition(): Closure - { - return function ( - TrafficLightsContext $context, - EventBehavior $eventBehavior - ): void { - $context->count += $eventBehavior->payload['value']; - }; + public function __invoke( + TrafficLightsContext $context, + EventBehavior $eventBehavior + ): void { + $context->count += $eventBehavior->payload['value']; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php b/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php index 91c1453..bb695a6 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/DecrementAction.php @@ -4,16 +4,13 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class DecrementAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): void { - return function (TrafficLightsContext $context): void { - $context->count--; - }; + $context->count--; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php b/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php index 12a4250..bc2efed 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/DoNothingInsideClassAction.php @@ -4,14 +4,11 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class DoNothingInsideClassAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(): void { - return function (): void { - }; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php b/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php index e549110..3307b33 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/IncrementAction.php @@ -4,16 +4,13 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class IncrementAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): void { - return function (TrafficLightsContext $context): void { - $context->count++; - }; + $context->count++; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php b/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php index 0d1c5ca..cb69a1d 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/MultiplyByTwoAction.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -12,10 +11,8 @@ class MultiplyByTwoAction extends ActionBehavior { public bool $shouldLog = true; - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): void { - return function (TrafficLightsContext $context): void { - $context->count *= 2; - }; + $context->count *= 2; } } diff --git a/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php b/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php index b0ab408..8429fcf 100644 --- a/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php +++ b/tests/Stubs/Machines/TrafficLights/Actions/SubtractValueAction.php @@ -4,20 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Actions; -use Closure; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; class SubtractValueAction extends ActionBehavior { - public function definition(): Closure - { - return function ( - TrafficLightsContext $context, - EventBehavior $eventBehavior - ): void { - $context->count -= $eventBehavior->payload['value']; - }; + public function __invoke( + TrafficLightsContext $context, + EventBehavior $eventBehavior, + ): void { + $context->count -= $eventBehavior->payload['value']; } } diff --git a/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php b/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php index f5e9d22..df76d18 100644 --- a/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php +++ b/tests/Stubs/Machines/TrafficLights/Guards/IsEvenGuard.php @@ -4,7 +4,6 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\Guards; -use Closure; use Tarfinlabs\EventMachine\Behavior\ValidationGuardBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; @@ -13,10 +12,8 @@ class IsEvenGuard extends ValidationGuardBehavior public ?string $errorMessage = 'Count is not even'; public bool $shouldLog = true; - public function definition(): Closure + public function __invoke(TrafficLightsContext $context): bool { - return function (TrafficLightsContext $context): bool { - return $context->count % 2 === 0; - }; + return $context->count % 2 === 0; } } diff --git a/tests/Stubs/Machines/Xyz/Actions/XAction.php b/tests/Stubs/Machines/Xyz/Actions/XAction.php index fbecd1b..abb839b 100644 --- a/tests/Stubs/Machines/Xyz/Actions/XAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/XAction.php @@ -4,18 +4,15 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class XAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(ContextManager $context): void { - return function (ContextManager $context): void { - $context->value .= 'x'; + $context->value .= 'x'; - $this->raise(['type' => '@x']); - }; + $this->raise(['type' => '@x']); } } diff --git a/tests/Stubs/Machines/Xyz/Actions/YAction.php b/tests/Stubs/Machines/Xyz/Actions/YAction.php index 7fcdcb5..2dec6e9 100644 --- a/tests/Stubs/Machines/Xyz/Actions/YAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/YAction.php @@ -4,19 +4,16 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; use Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Events\YEvent; class YAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(ContextManager $context): void { - return function (ContextManager $context): void { - $context->value .= 'y'; + $context->value .= 'y'; - $this->raise(new YEvent()); - }; + $this->raise(new YEvent()); } } diff --git a/tests/Stubs/Machines/Xyz/Actions/ZAction.php b/tests/Stubs/Machines/Xyz/Actions/ZAction.php index 1b5fc23..67f8555 100644 --- a/tests/Stubs/Machines/Xyz/Actions/ZAction.php +++ b/tests/Stubs/Machines/Xyz/Actions/ZAction.php @@ -4,18 +4,15 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Machines\Xyz\Actions; -use Closure; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Behavior\ActionBehavior; class ZAction extends ActionBehavior { - public function definition(): Closure + public function __invoke(ContextManager $context): void { - return function (ContextManager $context): void { - $context->value .= 'z'; + $context->value .= 'z'; - $this->raise(['type' => '@z']); - }; + $this->raise(['type' => '@z']); } } diff --git a/tests/Stubs/Results/GreenResult.php b/tests/Stubs/Results/GreenResult.php index e9145dc..8df37fa 100644 --- a/tests/Stubs/Results/GreenResult.php +++ b/tests/Stubs/Results/GreenResult.php @@ -4,16 +4,13 @@ namespace Tarfinlabs\EventMachine\Tests\Stubs\Results; -use Closure; use Illuminate\Support\Carbon; use Tarfinlabs\EventMachine\Behavior\ResultBehavior; class GreenResult extends ResultBehavior { - public function definition(): Closure + public function __invoke(): Carbon { - return function (): Carbon { - return now(); - }; + return now(); } } From 4d8aac08aec4b59a853f9c68685bb9220d8ff81d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 21:54:30 +0300 Subject: [PATCH 27/33] WEB-4344: Add ReflectionException to runActions docblock The runActions method in TransitionBranch.php now includes ReflectionException in the docblock to enhance user understanding. The ReflectionException error indicates issues with retrieving information about classes, interfaces, and methods during runtime, thus this helps users better anticipate potential problem points in this method. --- src/Definition/TransitionBranch.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Definition/TransitionBranch.php b/src/Definition/TransitionBranch.php index 4710e0c..5dfa203 100644 --- a/src/Definition/TransitionBranch.php +++ b/src/Definition/TransitionBranch.php @@ -166,6 +166,8 @@ protected function initializeInlineBehaviors(array $inlineBehaviors, BehaviorTyp * If there are no actions associated with the transition definition, do nothing. * * @param EventBehavior|null $eventBehavior The event or null if none is provided. + * + * @throws \ReflectionException */ public function runActions( State $state, From 145b3991c301bedb6296c8d88fb499338d8d95ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 21:54:47 +0300 Subject: [PATCH 28/33] WEB-4344: Implement centralized parameter injection for invokable behaviors Added a new static function `injectInvokableBehaviorParameters` to the `InvokableBehavior` class. This function injects parameters into invokable behaviors and it's utilized in `MachineDefinition` and `TransitionDefinition` classes, replacing and simplifying duplicated code. This update enhances the overall maintenance and readability of the code. --- src/Behavior/InvokableBehavior.php | 53 +++++++++++++++++++++++++ src/Definition/MachineDefinition.php | 38 +++++------------- src/Definition/TransitionDefinition.php | 35 ++++------------ 3 files changed, 70 insertions(+), 56 deletions(-) diff --git a/src/Behavior/InvokableBehavior.php b/src/Behavior/InvokableBehavior.php index 3e562fa..af0ad2b 100644 --- a/src/Behavior/InvokableBehavior.php +++ b/src/Behavior/InvokableBehavior.php @@ -4,8 +4,11 @@ namespace Tarfinlabs\EventMachine\Behavior; +use ReflectionMethod; +use ReflectionFunction; use Illuminate\Support\Str; use Illuminate\Support\Collection; +use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Exceptions\MissingMachineContextException; @@ -113,4 +116,54 @@ public static function getType(): string ->classBasename() ->toString(); } + + /** + * Injects invokable behavior parameters. + * + * Retrieves the parameters of the given invokable behavior and injects the corresponding values + * based on the provided state, event behavior, and action arguments. + * The injected values are added to an array and returned. + * + * @param callable $actionBehavior The invokable behavior to inject parameters for. + * @param State $state The state object used for parameter matching. + * @param EventBehavior|null $eventBehavior The event behavior used for parameter matching. (Optional) + * @param array|null $actionArguments The action arguments used for parameter matching. (Optional) + * + * @return array The injected invokable behavior parameters. + * + * @throws \ReflectionException + */ + public static function injectInvokableBehaviorParameters( + callable $actionBehavior, + State $state, + EventBehavior $eventBehavior = null, + array $actionArguments = null, + ): array { + $invocableBehaviorParameters = []; + + $invocableBehaviorReflection = $actionBehavior instanceof InvokableBehavior + ? new ReflectionMethod($actionBehavior, '__invoke') + : new ReflectionFunction($actionBehavior); + + foreach ($invocableBehaviorReflection->getParameters() as $parameter) { + $parameterType = $parameter->getType(); + + $typeName = $parameterType instanceof ReflectionUnionType + ? $parameterType->getTypes()[0]->getName() + : $parameterType->getName(); + + $value = match (true) { + is_a($state->context, $typeName) => $state->context, // ContextManager + is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior + is_a($state, $typeName) => $state, // State + is_a($state->history, $typeName) => $state->history, // EventCollection + $typeName === 'array' => $actionArguments, // Behavior Arguments + default => null, + }; + + $invocableBehaviorParameters[] = $value; + } + + return $invocableBehaviorParameters; + } } diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index 73eb295..8198437 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -4,9 +4,6 @@ namespace Tarfinlabs\EventMachine\Definition; -use ReflectionMethod; -use ReflectionFunction; -use ReflectionUnionType; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\ContextManager; @@ -729,33 +726,16 @@ public function runAction( // Get the number of events in the queue before the action is executed. $numberOfEventsInQueue = $this->eventQueue->count(); - $actionBehaviorParameters = []; - - $actionBehaviorReflection = $actionBehavior instanceof InvokableBehavior - ? new ReflectionMethod($actionBehavior, '__invoke') - : new ReflectionFunction($actionBehavior); - - foreach ($actionBehaviorReflection->getParameters() as $parameter) { - $parameterType = $parameter->getType(); - - $typeName = $parameterType instanceof ReflectionUnionType - ? $parameterType->getTypes()[0]->getName() - : $parameterType->getName(); - - $value = match (true) { - is_a($state->context, $typeName) => $state->context, // ContextManager - is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior - is_a($state, $typeName) => $state, // State - is_a($state->history, $typeName) => $state->history, // EventCollection - $typeName === 'array' => $actionArguments, // Behavior Arguments - default => null, - }; - - $actionBehaviorParameters[] = $value; - } + // Inject action behavior parameters + $actionBehaviorParemeters = InvokableBehavior::injectInvokableBehaviorParameters( + actionBehavior: $actionBehavior, + state: $state, + eventBehavior: $eventBehavior, + actionArguments: $actionArguments + ); - // Execute the action behavior. - ($actionBehavior)(...$actionBehaviorParameters); + // Execute the action behavior + ($actionBehavior)(...$actionBehaviorParemeters); // Get the number of events in the queue after the action is executed. $newNumberOfEventsInQueue = $this->eventQueue->count(); diff --git a/src/Definition/TransitionDefinition.php b/src/Definition/TransitionDefinition.php index 6ab0694..35a600f 100644 --- a/src/Definition/TransitionDefinition.php +++ b/src/Definition/TransitionDefinition.php @@ -4,9 +4,6 @@ namespace Tarfinlabs\EventMachine\Definition; -use ReflectionMethod; -use ReflectionFunction; -use ReflectionUnionType; use Tarfinlabs\EventMachine\Actor\State; use Tarfinlabs\EventMachine\Enums\BehaviorType; use Tarfinlabs\EventMachine\Enums\InternalEvent; @@ -175,31 +172,15 @@ public function getFirstValidTransitionBranch( $guardBehavior->validateRequiredContext($state->context); } - $guardBehaviorParameters = []; - - $guardBehaviorReflection = $guardBehavior instanceof InvokableBehavior - ? new ReflectionMethod($guardBehavior, '__invoke') - : new ReflectionFunction($guardBehavior); - - foreach ($guardBehaviorReflection->getParameters() as $parameter) { - $parameterType = $parameter->getType(); - - $typeName = $parameterType instanceof ReflectionUnionType - ? $parameterType->getTypes()[0]->getName() - : $parameterType->getName(); - - $value = match (true) { - is_a($state->context, $typeName) => $state->context, // ContextManager - is_a($eventBehavior, $typeName) => $eventBehavior, // EventBehavior - is_a($state, $typeName) => $state, // State - is_a($state->history, $typeName) => $state->history, // EventCollection - $typeName === 'array' => $guardArguments, // Behavior Arguments - default => null, - }; - - $guardBehaviorParameters[] = $value; - } + // Inject guard behavior parameters + $guardBehaviorParameters = InvokableBehavior::injectInvokableBehaviorParameters( + actionBehavior: $guardBehavior, + state: $state, + eventBehavior: $eventBehavior, + actionArguments: $guardArguments, + ); + // Execute the guard behavior $guardResult = ($guardBehavior)(...$guardBehaviorParameters); if ($guardResult === false) { From baa4fd8a564aa9bed8627c99977a8a25d7dcb38a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Tue, 5 Dec 2023 22:14:50 +0300 Subject: [PATCH 29/33] WEB-4344: Refactored InvokableBehavior injection logic Introduced a new ReflectionUnionType to the InvokableBehavior class to centralize parameter injection for invokable behaviors. Enhanced the readability and maintenance of the code by simplifying the reflection logic used in MachineDefinition and TransitionDefinition classes. --- src/Behavior/InvokableBehavior.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Behavior/InvokableBehavior.php b/src/Behavior/InvokableBehavior.php index af0ad2b..b5621b9 100644 --- a/src/Behavior/InvokableBehavior.php +++ b/src/Behavior/InvokableBehavior.php @@ -6,6 +6,7 @@ use ReflectionMethod; use ReflectionFunction; +use ReflectionUnionType; use Illuminate\Support\Str; use Illuminate\Support\Collection; use Tarfinlabs\EventMachine\Actor\State; @@ -141,7 +142,7 @@ public static function injectInvokableBehaviorParameters( ): array { $invocableBehaviorParameters = []; - $invocableBehaviorReflection = $actionBehavior instanceof InvokableBehavior + $invocableBehaviorReflection = $actionBehavior instanceof self ? new ReflectionMethod($actionBehavior, '__invoke') : new ReflectionFunction($actionBehavior); From d1e31e8d41d46e4a2e7b609fbc07dc929a67708c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 12 Jan 2024 00:38:17 +0300 Subject: [PATCH 30/33] WEB-4344: Apply styles --- src/Behavior/InvokableBehavior.php | 4 ++-- tests/InvokableBehaviorArgumentsTest.php | 6 +++--- tests/Stubs/Guards/IsTimerValidValidationGuard.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Behavior/InvokableBehavior.php b/src/Behavior/InvokableBehavior.php index b5621b9..3f165ef 100644 --- a/src/Behavior/InvokableBehavior.php +++ b/src/Behavior/InvokableBehavior.php @@ -137,8 +137,8 @@ public static function getType(): string public static function injectInvokableBehaviorParameters( callable $actionBehavior, State $state, - EventBehavior $eventBehavior = null, - array $actionArguments = null, + ?EventBehavior $eventBehavior = null, + ?array $actionArguments = null, ): array { $invocableBehaviorParameters = []; diff --git a/tests/InvokableBehaviorArgumentsTest.php b/tests/InvokableBehaviorArgumentsTest.php index 96298dc..e48af7b 100644 --- a/tests/InvokableBehaviorArgumentsTest.php +++ b/tests/InvokableBehaviorArgumentsTest.php @@ -25,7 +25,7 @@ ], behavior: [ 'actions' => [ - 'additionAction' => function (ContextManager $ctx, EventDefinition $ed, array $arguments = null): void { + 'additionAction' => function (ContextManager $ctx, EventDefinition $ed, ?array $arguments = null): void { $ctx->count += array_sum($arguments); }, ], @@ -57,12 +57,12 @@ ], behavior: [ 'actions' => [ - 'additionAction' => function (ContextManager $context, EventDefinition $eventDefinition, array $arguments = null): void { + 'additionAction' => function (ContextManager $context, EventDefinition $eventDefinition, ?array $arguments = null): void { $context->count += array_sum($arguments); }, ], 'guards' => [ - 'biggerThan' => function (ContextManager $context, EventDefinition $eventDefinition, array $arguments = null): bool { + 'biggerThan' => function (ContextManager $context, EventDefinition $eventDefinition, ?array $arguments = null): bool { return $context->count > $arguments[0]; }, ], diff --git a/tests/Stubs/Guards/IsTimerValidValidationGuard.php b/tests/Stubs/Guards/IsTimerValidValidationGuard.php index 6dcf44e..5cc3972 100644 --- a/tests/Stubs/Guards/IsTimerValidValidationGuard.php +++ b/tests/Stubs/Guards/IsTimerValidValidationGuard.php @@ -13,7 +13,7 @@ class IsTimerValidValidationGuard extends ValidationGuardBehavior public function __invoke( ContextManager $context, EventBehavior $eventBehavior, - array $arguments = null, + ?array $arguments = null, ): bool { $value = $eventBehavior->payload['value']; $result = $value > (int) $arguments[0]; From f7b469aa59bd005eb025967d1408eefbf5cc5f03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 12 Jan 2024 00:38:25 +0300 Subject: [PATCH 31/33] WEB-4344: Update pint command in composer.json The pint command in the composer.json file has been updated to include --config flag. This specifies the configuration file to use when running the pint command, improving flexibility in running lint checks. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ec66172..1f961d5 100644 --- a/composer.json +++ b/composer.json @@ -52,7 +52,7 @@ "profile": "vendor/bin/pest --profile --colors=always --order-by=random --configuration=phpunit.xml.dist", "coverage": "vendor/bin/pest --coverage --colors=always --order-by=random --configuration=phpunit.xml.dist", "coveragep": "vendor/bin/pest --parallel --coverage --colors=always --order-by=random --configuration=phpunit.xml.dist", - "pint": "vendor/bin/pint", + "pint": "vendor/bin/pint --config=pint.json", "lint": "@pint", "lintc": "vendor/bin/pint && (git diff-index --quiet HEAD || (git add . && git commit -m 'chore: Fix styling'))", "infection": "vendor/bin/infection --test-framework=pest --show-mutations --threads=max --min-msi=100 --min-covered-msi=100 --ansi" From 4d2a27fcb68d1c31fe6e0322fd764f52a32a3b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 12 Jan 2024 00:52:56 +0300 Subject: [PATCH 32/33] WEB-4344: Change ResultBehaviour type annotation to callable The type annotation for the variable $resultBehavior in the Machine.php file has been changed from \Tarfinlabs\EventMachine\Behavior\ResultBehavior to callable. This change ensures the $resultBehavior variable can accept any callable function, thereby making the code more versatile. --- src/Actor/Machine.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Actor/Machine.php b/src/Actor/Machine.php index e146e6d..a05a32b 100644 --- a/src/Actor/Machine.php +++ b/src/Actor/Machine.php @@ -493,7 +493,7 @@ public function result(): mixed $resultBehavior = new $resultBehavior(); } - /* @var \Tarfinlabs\EventMachine\Behavior\ResultBehavior $resultBehavior */ + /* @var callable $resultBehavior */ return $resultBehavior( $this->state->context, $this->state->currentEventBehavior, From 039bc551e8b85bc79512f61db70fba3d560fb788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 12 Jan 2024 01:13:03 +0300 Subject: [PATCH 33/33] WEB-4344: Refactor ResultBehavior definition to an invokable method The class method definition in ResultBehavior has been refactored to an invokable. A previous anonymous function definition has been replaced with the __invoke magic method, offering a more concise syntax and enhancing the object's versatility by making it directly callable. --- tests/ActionTest.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/ActionTest.php b/tests/ActionTest.php index 17b708c..82655e0 100644 --- a/tests/ActionTest.php +++ b/tests/ActionTest.php @@ -92,17 +92,15 @@ $value = random_int(10, 20); $multipleWithItselfAction = new class extends ResultBehavior { - public function definition(): Closure + public function __invoke(EventBehavior $event): int { - return function (EventBehavior $eventBehavior): int { - return $eventBehavior->payload['value'] * $eventBehavior->payload['value']; - }; + return $event->payload['value'] * $event->payload['value']; } }; // 2. Act - $result = $multipleWithItselfAction->definition()( - eventBehavior: EventDefinition::from([ + $result = $multipleWithItselfAction( + EventDefinition::from([ 'type' => 'ADD', 'payload' => [ 'value' => $value,