From d30af74b198ddb45b2001ebff4a3317c3981d209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:08:22 +0300 Subject: [PATCH 01/50] WB-784: feat(state-config): add StateConfigValidator class Introduce a StateConfigValidator class to validate machine configuration keys and state types. This establishes clear validation rules for root, state, and transition levels, improving configuration consistency. --- src/StateConfigValidator.php | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/StateConfigValidator.php diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php new file mode 100644 index 0000000..5d1f8b3 --- /dev/null +++ b/src/StateConfigValidator.php @@ -0,0 +1,28 @@ + Date: Thu, 12 Dec 2024 22:08:56 +0300 Subject: [PATCH 02/50] WB-784: feat(state-config-validator): add array/string normalization utility Add normalizeArrayOrString method to normalize input into an array or null, throwing an exception for unsupported types. --- src/StateConfigValidator.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 5d1f8b3..9fe49b9 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -4,6 +4,8 @@ namespace Tarfinlabs\EventMachine; +use InvalidArgumentException; + class StateConfigValidator { /** Allowed keys at different levels of the machine configuration */ @@ -25,4 +27,26 @@ class StateConfigValidator private const VALID_STATE_TYPES = [ 'atomic', 'compound', 'final', ]; + + /** + * Normalizes the given value into an array or returns null. + * + * @throws InvalidArgumentException If the value is neither string, array, nor null. + */ + private static function normalizeArrayOrString(mixed $value): ?array + { + if ($value === null) { + return null; + } + + if (is_string($value)) { + return [$value]; + } + + if (is_array($value)) { + return $value; + } + + throw new InvalidArgumentException('Value must be string, array or null'); + } } From 08d1dad8798fec157ddd33a5efd587496a5cb33d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:09:11 +0300 Subject: [PATCH 03/50] WB-784: feat(state-config-validator): add machine config validation method Add `validate` method to verify the structure of machine configurations, including root-level settings, states, and transitions. --- src/StateConfigValidator.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 9fe49b9..0c95174 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -49,4 +49,35 @@ private static function normalizeArrayOrString(mixed $value): ?array throw new InvalidArgumentException('Value must be string, array or null'); } + + /** + * Validates the machine configuration structure. + * + * @throws InvalidArgumentException + */ + public static function validate(?array $config): void + { + if ($config === null) { + return; + } + + // Validate root level configuration + self::validateRootConfig($config); + + // Validate states if they exist + if (isset($config['states'])) { + if (!is_array($config['states'])) { + throw new InvalidArgumentException('States configuration must be an array.'); + } + + foreach ($config['states'] as $stateName => $stateConfig) { + self::validateStateConfig($stateConfig, $stateName); + } + } + + // Validate root level transitions if they exist + if (isset($config['on'])) { + self::validateTransitionsConfig($config['on'], 'root'); + } + } } From 9c5fbf3f8d352e556d12c9acd90dc30e40470a28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:09:34 +0300 Subject: [PATCH 04/50] WB-784: feat(validator): add root-level configuration validation Add `validateRootConfig` method to ensure root-level keys in config are valid. Throws `InvalidArgumentException` for any invalid keys. --- src/StateConfigValidator.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 0c95174..8c23d01 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -80,4 +80,24 @@ public static function validate(?array $config): void self::validateTransitionsConfig($config['on'], 'root'); } } + + /** + * Validates root level configuration. + * + * @throws InvalidArgumentException + */ + private static function validateRootConfig(array $config): void + { + $invalidRootKeys = array_diff( + array_keys($config), + self::ALLOWED_ROOT_KEYS + ); + + if (!empty($invalidRootKeys)) { + throw new InvalidArgumentException( + 'Invalid root level configuration keys: '.implode(', ', $invalidRootKeys). + '. Allowed keys are: '.implode(', ', self::ALLOWED_ROOT_KEYS) + ); + } + } } From ca46f32254397348570fc874660a807b97713aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:14:02 +0300 Subject: [PATCH 05/50] WB-784: refactor(stateconfigvalidator): use named arguments for clarity Updated method calls to use named arguments, improving code readability and maintainability. --- src/StateConfigValidator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 8c23d01..da28a42 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -67,7 +67,7 @@ public static function validate(?array $config): void // Validate states if they exist if (isset($config['states'])) { if (!is_array($config['states'])) { - throw new InvalidArgumentException('States configuration must be an array.'); + throw new InvalidArgumentException(message: 'States configuration must be an array.'); } foreach ($config['states'] as $stateName => $stateConfig) { @@ -77,7 +77,7 @@ public static function validate(?array $config): void // Validate root level transitions if they exist if (isset($config['on'])) { - self::validateTransitionsConfig($config['on'], 'root'); + self::validateTransitionsConfig(transitionsConfig: $config['on'], path: 'root'); } } @@ -95,8 +95,8 @@ private static function validateRootConfig(array $config): void if (!empty($invalidRootKeys)) { throw new InvalidArgumentException( - 'Invalid root level configuration keys: '.implode(', ', $invalidRootKeys). - '. Allowed keys are: '.implode(', ', self::ALLOWED_ROOT_KEYS) + message: 'Invalid root level configuration keys: '.implode(separator: ', ', array: $invalidRootKeys). + '. Allowed keys are: '.implode(separator: ', ', array: self::ALLOWED_ROOT_KEYS) ); } } From 53b6d8d22893cf073d10513bbdacfc40b2ab4772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:15:51 +0300 Subject: [PATCH 06/50] WB-784: feat(config-validation): add state configuration validation Introduce a new `validateStateConfig` method in `StateConfigValidator` to ensure proper state configurations. This includes checks for invalid keys, transition placement, state types, entry/exit actions, nested states, and transitions under the 'on' key. --- src/StateConfigValidator.php | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index da28a42..06d4219 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -100,4 +100,64 @@ private static function validateRootConfig(array $config): void ); } } + + /** + * Validates a single state's configuration. + * + * @throws InvalidArgumentException + */ + private static function validateStateConfig(?array $stateConfig, string $path): void + { + if ($stateConfig === null) { + return; + } + + // Check for transitions defined outside 'on' + if (isset($stateConfig['@always']) || array_key_exists(key: '@always', array: $stateConfig)) { + throw new InvalidArgumentException( + message: "State '{$path}' has transitions defined directly. ". + "All transitions including '@always' must be defined under the 'on' key." + ); + } + + // Validate state keys + $invalidKeys = array_diff(array_keys($stateConfig), self::ALLOWED_STATE_KEYS); + if (!empty($invalidKeys)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid keys: ".implode(separator: ', ', array: $invalidKeys). + '. Allowed keys are: '.implode(separator: ', ', array: self::ALLOWED_STATE_KEYS) + ); + } + + // Validate state type if specified + if (isset($stateConfig['type'])) { + self::validateStateType(stateConfig: $stateConfig, path: $path); + } + + // Validate entry/exit actions + self::validateStateActions(stateConfig: $stateConfig, path: $path); + + // Final state validations + if (isset($stateConfig['type']) && $stateConfig['type'] === 'final') { + self::validateFinalState(stateConfig: $stateConfig, path: $path); + } + + // Validate nested states + if (isset($stateConfig['states'])) { + if (!is_array($stateConfig['states'])) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid states configuration. States must be an array." + ); + } + + foreach ($stateConfig['states'] as $childKey => $childState) { + self::validateStateConfig(stateConfig: $childState, path: "{$path}.{$childKey}"); + } + } + + // Validate transitions under 'on' + if (isset($stateConfig['on'])) { + self::validateTransitionsConfig(transitionsConfig: $stateConfig['on'], path: $path); + } + } } From 789e27e38b1f1357c772d7892b8c2b45be1c733b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:16:36 +0300 Subject: [PATCH 07/50] WB-784: feat(state-validator): add state type validation Introduce `validateStateType` method to enforce allowed state types. Throws `InvalidArgumentException` for invalid states, improving validation robustness. --- src/StateConfigValidator.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 06d4219..9a9077f 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -160,4 +160,19 @@ private static function validateStateConfig(?array $stateConfig, string $path): self::validateTransitionsConfig(transitionsConfig: $stateConfig['on'], path: $path); } } + + /** + * Validates state type configuration. + * + * @throws InvalidArgumentException + */ + private static function validateStateType(array $stateConfig, string $path): void + { + if (!in_array($stateConfig['type'], haystack: self::VALID_STATE_TYPES, strict: true)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid type: {$stateConfig['type']}. ". + 'Allowed types are: '.implode(separator: ', ', array: self::VALID_STATE_TYPES) + ); + } + } } From d1ef57b98fcd436ab3701673eaa6a8c9b22a7191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:17:04 +0300 Subject: [PATCH 08/50] WB-784: feat(state-validator): add validation for final state constraints Ensure final states cannot have transitions or child states. --- src/StateConfigValidator.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 9a9077f..8789a70 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -175,4 +175,24 @@ private static function validateStateType(array $stateConfig, string $path): voi ); } } + + /** + * Validates final state constraints. + * + * @throws InvalidArgumentException + */ + private static function validateFinalState(array $stateConfig, string $path): void + { + if (isset($stateConfig['on'])) { + throw new InvalidArgumentException( + message: "Final state '{$path}' cannot have transitions" + ); + } + + if (isset($stateConfig['states'])) { + throw new InvalidArgumentException( + message: "Final state '{$path}' cannot have child states" + ); + } + } } From b494aa54973def3c438a83d0ae9776ec0c4c4054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:17:33 +0300 Subject: [PATCH 09/50] WB-784: feat(state-config-validator): add validation for state entry/exit actions Ensure entry and exit actions in state configurations are either a string or an array. Throws exception for invalid types to improve error handling and robustness. --- src/StateConfigValidator.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 8789a70..7623d6b 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -195,4 +195,24 @@ private static function validateFinalState(array $stateConfig, string $path): vo ); } } + + /** + * Validates state entry and exit actions. + * + * @throws InvalidArgumentException + */ + private static function validateStateActions(array $stateConfig, string $path): void + { + foreach (['entry', 'exit'] as $actionType) { + if (isset($stateConfig[$actionType])) { + $actions = $stateConfig[$actionType]; + if (!is_string($actions) && !is_array($actions)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid {$actionType} actions configuration. ". + 'Actions must be an array or string.' + ); + } + } + } + } } From fa683419626fca45e73999bdebf6c7437b6a4ffa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:18:01 +0300 Subject: [PATCH 10/50] WB-784: feat(state-validation): add transitions configuration validation Add a static method to validate transitions configuration in StateConfigValidator. Ensures 'on' definition is an array and validates each transition. Throws InvalidArgumentException for invalid configurations. --- src/StateConfigValidator.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 7623d6b..de54f52 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -215,4 +215,22 @@ private static function validateStateActions(array $stateConfig, string $path): } } } + + /** + * Validates transitions configuration. + * + * @throws InvalidArgumentException + */ + private static function validateTransitionsConfig(mixed $transitionsConfig, string $path): void + { + if (!is_array($transitionsConfig)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid 'on' definition. 'on' must be an array of transitions." + ); + } + + foreach ($transitionsConfig as $eventName => $transition) { + self::validateTransition(transition: $transition, path: $path, eventName: $eventName); + } + } } From b4cc932017021f478db98aa8d15308463ea8b875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:18:40 +0300 Subject: [PATCH 11/50] WB-784: feat(state-validator): add validation for single transition config Add `validateTransition` method to ensure proper validation for single and guarded transitions. This enhances error handling for invalid transition configurations. --- src/StateConfigValidator.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index de54f52..aa49a02 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -233,4 +233,40 @@ private static function validateTransitionsConfig(mixed $transitionsConfig, stri self::validateTransition(transition: $transition, path: $path, eventName: $eventName); } } + + /** + * Validates a single transition configuration. + */ + private static function validateTransition( + mixed $transition, + string $path, + string $eventName + ): void { + if ($transition === null) { + return; + } + + if (is_string($transition)) { + return; + } + + if (!is_array($transition)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid transition for event '{$eventName}'. ". + 'Transition must be a string (target state) or an array (transition config).' + ); + } + + // If it's an array of conditions (guarded transitions) + if (array_is_list($transition)) { + self::validateGuardedTransitions($transition, $path, $eventName); + foreach ($transition as &$condition) { + self::validateTransitionConfig(transitionConfig: $condition, path: $path, eventName: $eventName); + } + + return; + } + + self::validateTransitionConfig(transitionConfig: $transition, path: $path, eventName: $eventName); + } } From f808b509219345d9748754fc668124fba623ccb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:20:27 +0300 Subject: [PATCH 12/50] WB-784: feat(validator): add transition config validation Add validateTransitionConfig method to check transition configuration, ensuring allowed keys and proper normalization. Throws InvalidArgumentException for invalid keys, improving state config validation robustness. --- src/StateConfigValidator.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index aa49a02..2556d53 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -269,4 +269,26 @@ private static function validateTransition( self::validateTransitionConfig(transitionConfig: $transition, path: $path, eventName: $eventName); } + + /** + * Validates the configuration of a single transition. + */ + private static function validateTransitionConfig( + array &$transitionConfig, + string $path, + string $eventName + ): void { + // Validate allowed keys + $invalidKeys = array_diff(array_keys($transitionConfig), self::ALLOWED_TRANSITION_KEYS); + if (!empty($invalidKeys)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid keys in transition config for event '{$eventName}': ". + implode(separator: ', ', array: $invalidKeys). + '. Allowed keys are: '.implode(separator: ', ', array: self::ALLOWED_TRANSITION_KEYS) + ); + } + + // Normalize and validate behaviors + self::validateTransitionBehaviors(transitionConfig: $transitionConfig, path: $path, eventName: $eventName); + } } From b740b52f6d86454000e8ce5960b9544b003289b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:21:13 +0300 Subject: [PATCH 13/50] WB-784: feat(validator): add transition behaviors validation Introduce `validateTransitionBehaviors` to verify and normalize guards, actions, and calculators in state transition configurations. Throws clear errors for invalid input formats. --- src/StateConfigValidator.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 2556d53..b0880b8 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -291,4 +291,28 @@ private static function validateTransitionConfig( // Normalize and validate behaviors self::validateTransitionBehaviors(transitionConfig: $transitionConfig, path: $path, eventName: $eventName); } + + /** + * Validates and normalizes transition behaviors (guards, actions, calculators). + */ + private static function validateTransitionBehaviors( + array &$transitionConfig, + string $path, + string $eventName + ): void { + $behaviors = ['guards', 'actions', 'calculators']; + + foreach ($behaviors as $behavior) { + if (isset($transitionConfig[$behavior])) { + try { + $transitionConfig[$behavior] = self::normalizeArrayOrString(value: $transitionConfig[$behavior]); + } catch (InvalidArgumentException) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid {$behavior} configuration for event '{$eventName}'. ". + "{$behavior} must be an array or string." + ); + } + } + } + } } From 1cf3ea8ea6af4273310b874030ba0c4f63831f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:22:01 +0300 Subject: [PATCH 14/50] WB-784: feat(validator): add validation for guarded transitions Add `validateGuardedTransitions` method to ensure guarded transitions have valid conditions, targets are defined, and default conditions are ordered correctly. --- src/StateConfigValidator.php | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index b0880b8..d916b26 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -315,4 +315,46 @@ private static function validateTransitionBehaviors( } } } + + /** + * Validates guarded transitions with multiple conditions. + */ + private static function validateGuardedTransitions(array $conditions, string $path, string $eventName): void + { + if (empty($conditions)) { + throw new InvalidArgumentException( + message: "State '{$path}' has empty conditions array for event '{$eventName}'. ". + 'Guarded transitions must have at least one condition.' + ); + } + + foreach ($conditions as $index => $condition) { + if (!is_array($condition)) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid condition at index {$index} for event '{$eventName}'. ". + 'Each condition must be an array.' + ); + } + + if (!isset($condition['target'])) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid condition at index {$index} for event '{$eventName}'. ". + 'Each condition must have a target.' + ); + } + + // Check if this is a default condition (no guards) + $isDefaultCondition = !isset($condition['guards']); + + if ($isDefaultCondition) { + // If this is not the last condition + if ($index !== count($conditions) - 1) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid conditions order for event '{$eventName}'. ". + 'Default condition (no guards) must be the last condition.' + ); + } + } + } + } } From 2ba249c4c0194392242daceed69b8b1db4420d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:22:06 +0300 Subject: [PATCH 15/50] WB-784: feat(machine): add state config validation during initialization Add `StateConfigValidator::validate` to ensure machine configuration integrity during initialization. Validates the `config` and `id` properties to prevent misconfiguration issues. --- src/Definition/MachineDefinition.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index bb88c09..dfa8305 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -9,6 +9,7 @@ use Tarfinlabs\EventMachine\ContextManager; use Tarfinlabs\EventMachine\Enums\BehaviorType; use Tarfinlabs\EventMachine\Enums\InternalEvent; +use Tarfinlabs\EventMachine\StateConfigValidator; use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Enums\TransitionProperty; use Tarfinlabs\EventMachine\Enums\StateDefinitionType; @@ -84,6 +85,8 @@ private function __construct( public ?array $scenarios, public string $delimiter = self::STATE_DELIMITER, ) { + StateConfigValidator::validate($config, $this->id); + $this->scenariosEnabled = isset($this->config['scenarios_enabled']) && $this->config['scenarios_enabled'] === true; $this->shouldPersist = $this->config['should_persist'] ?? $this->shouldPersist; From e1840d1a09d8aeaacb45edcd34d9fb9fb3b21297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:22:59 +0300 Subject: [PATCH 16/50] WB-784: test(state-config-validator): add test for root key validation Add a test to ensure invalid root-level configuration keys in state machine definitions throw appropriate exceptions. --- tests/StateConfigValidatorTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/StateConfigValidatorTest.php diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php new file mode 100644 index 0000000..c3f0033 --- /dev/null +++ b/tests/StateConfigValidatorTest.php @@ -0,0 +1,19 @@ + MachineDefinition::define([ + 'id' => 'machine', + 'invalid_key' => 'value', + 'another_invalid' => 'value', + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: 'Invalid root level configuration keys: invalid_key, another_invalid. Allowed keys are: id, version, initial, context, states, on, type, meta, entry, exit, description, scenarios_enabled, should_persist, delimiter' + ); +}); From 861b92f224f024911715c945b697e0e9fab2a387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:24:34 +0300 Subject: [PATCH 17/50] WB-784: test(stateconfigvalidator): add test for valid root level config --- tests/StateConfigValidatorTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index c3f0033..04c8503 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -17,3 +17,19 @@ exceptionMessage: 'Invalid root level configuration keys: invalid_key, another_invalid. Allowed keys are: id, version, initial, context, states, on, type, meta, entry, exit, description, scenarios_enabled, should_persist, delimiter' ); }); + +test('accepts valid root level configuration', function (): void { + // HINT: This test should contain all possible root level configuration keys + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'version' => '1.0.0', + 'initial' => 'state_a', + 'context' => ['some' => 'data'], + 'scenarios_enabled' => true, + 'should_persist' => true, + 'delimiter' => '.', + 'states' => [ + 'state_a' => [], + ], + ]))->not->toThrow(exception: InvalidArgumentException::class); +}); From 3bc2cebae3e28499229bd3d2aeff2312abb10d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:25:08 +0300 Subject: [PATCH 18/50] WB-784: test(stateconfigvalidator): add test for valid root level config --- tests/StateConfigValidatorTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 04c8503..5879e6d 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -33,3 +33,17 @@ ], ]))->not->toThrow(exception: InvalidArgumentException::class); }); + +test('accepts machine with root level transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'on' => [ + 'GLOBAL_EVENT' => 'state_b', + ], + 'states' => [ + 'state_a' => [], + 'state_b' => [], + ], + ]))->not->toThrow(InvalidArgumentException::class); +}); From 048f92a7b3380b2682a390cdefb34b9a25021f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:25:49 +0300 Subject: [PATCH 19/50] WB-784: test(state-config-validator): add test for invalid transition definition Add validation test to ensure transitions must be defined under the 'on' key, catching improper definitions with '@always'. --- tests/StateConfigValidatorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 5879e6d..2ee6744 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -47,3 +47,20 @@ ], ]))->not->toThrow(InvalidArgumentException::class); }); + +test('transitions must be defined under the on key', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'check', + 'states' => [ + 'check' => [ + '@always' => [ // Transition defined directly under state + 'target' => 'next', + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'check' has transitions defined directly. All transitions including '@always' must be defined under the 'on' key." + ); +}); From a1d48ca6c96a7b8cabba1866db49a856de58ea1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:26:39 +0300 Subject: [PATCH 20/50] WB-784: test(stateconfigvalidator): add test for validating 'on' property as array Add a test case to ensure that the 'on' property in state definitions is validated as an array, throwing an appropriate exception if invalid. --- tests/StateConfigValidatorTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 2ee6744..07ec021 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -64,3 +64,18 @@ exceptionMessage: "State 'check' has transitions defined directly. All transitions including '@always' must be defined under the 'on' key." ); }); + +test('validates on property is an array', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => 'invalid_string', // 'on' should be an array + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid 'on' definition. 'on' must be an array of transitions." + ); +}); From 599b019857840c5e733e74c6d76933a2c20b28f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:27:09 +0300 Subject: [PATCH 21/50] WB-784: test(stateconfigvalidator): add test for invalid transition target Add a test to ensure transition targets are validated as either a string or an array, raising an exception for invalid definitions. --- tests/StateConfigValidatorTest.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 07ec021..58b69f1 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -79,3 +79,20 @@ exceptionMessage: "State 'state_a' has invalid 'on' definition. 'on' must be an array of transitions." ); }); + +test('validates transition target is either string or array', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => true, // Invalid transition definition + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid transition for event 'EVENT'. Transition must be a string (target state) or an array (transition config)." + ); +}); From 67dd54f08ca088c1ad08e2c85bfa40af3adb39fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:30:33 +0300 Subject: [PATCH 22/50] WB-784: test(stateconfigvalidator): add test for allowed keys validation Add a test to ensure transition configurations throw an exception for invalid keys, verifying allowed keys in 'transition config' are strictly enforced. --- tests/StateConfigValidatorTest.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 58b69f1..598ad42 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -96,3 +96,23 @@ exceptionMessage: "State 'state_a' has invalid transition for event 'EVENT'. Transition must be a string (target state) or an array (transition config)." ); }); +test('validates allowed keys in transition config', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'invalid_key' => 'value', + 'another_invalid' => 'value', + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid keys in transition config for event 'EVENT': invalid_key, another_invalid. Allowed keys are: target, guards, actions, description, calculators" + ); +}); From f5a09bdb13c6f20396fdf6856ca1df07962a5ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:31:07 +0300 Subject: [PATCH 23/50] WB-784: test(stateconfigvalidator): add test for invalid state type validation Add a test to validate that state types must be 'atomic', 'compound', or 'final', and throw an exception for invalid types. --- tests/StateConfigValidatorTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 598ad42..07d59a9 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -116,3 +116,18 @@ exceptionMessage: "State 'state_a' has invalid keys in transition config for event 'EVENT': invalid_key, another_invalid. Allowed keys are: target, guards, actions, description, calculators" ); }); + +test('validates state type values', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'type' => 'invalid_type', // Type should be 'atomic', 'compound', or 'final' + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid type: invalid_type. Allowed types are: atomic, compound, final" + ); +}); From 1c9e1d56372dfb4137bac99b40e61b44f152b588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:31:48 +0300 Subject: [PATCH 24/50] WB-784: test(state-config-validator): add test for final state transitions validation Add a test to ensure final states do not have transitions, throwing an appropriate exception. --- tests/StateConfigValidatorTest.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 07d59a9..fac781a 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -131,3 +131,21 @@ exceptionMessage: "State 'state_a' has invalid type: invalid_type. Allowed types are: atomic, compound, final" ); }); + +test('validates final states have no transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'type' => 'final', + 'on' => [ + 'EVENT' => 'state_b', + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "Final state 'state_a' cannot have transitions" + ); +}); From 9e57651bea61571e8f2b38a6c8fd03cfad0bf97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:32:31 +0300 Subject: [PATCH 25/50] WB-784: test(stateconfigvalidator): add test for final states without child states Add test to ensure final states cannot have child states, throwing an appropriate exception. --- tests/StateConfigValidatorTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index fac781a..d6ca802 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -149,3 +149,22 @@ exceptionMessage: "Final state 'state_a' cannot have transitions" ); }); + +test('validates final states have no child states', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'type' => 'final', + 'states' => [ + 'child' => [], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "Final state 'state_a' cannot have child states" + ); +}); + From 0028e4c88362c87c99921ed748865b1848a429b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:34:43 +0300 Subject: [PATCH 26/50] WB-784: test(stateconfigvalidator): add test for comprehensive state configuration validation Add a new test to validate state configurations with all possible features, including initial states, transitions, guards, actions, and nested states. --- tests/StateConfigValidatorTest.php | 49 ++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index d6ca802..a08dd1f 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -6,6 +6,7 @@ use InvalidArgumentException; use Tarfinlabs\EventMachine\Definition\MachineDefinition; +use Tarfinlabs\EventMachine\Tests\Stubs\Machines\TrafficLights\TrafficLightsContext; test('validates root level configuration keys', function (): void { expect(fn () => MachineDefinition::define([ @@ -168,3 +169,51 @@ ); }); +test('accepts valid state configuration with all possible features', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'version' => '1.0.0', + 'initial' => 'state_a', + 'context' => TrafficLightsContext::class, + 'states' => [ + 'state_a' => [ + 'type' => 'compound', + 'initial' => 'child_a', + 'entry' => ['entryAction1', 'entryAction2'], + 'exit' => 'exitAction', + 'meta' => ['some' => 'data'], + 'description' => 'A compound state', + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'guards' => ['guard1', 'guard2'], + 'actions' => ['action1', 'action2'], + 'calculators' => ['calc1', 'calc2'], + 'description' => 'Transition to state B', + ], + '@always' => [ + [ + 'target' => 'state_b', + 'guards' => 'guard1', + 'description' => 'Always transition when guard passes', + ], + [ + 'target' => 'state_c', + 'description' => 'Default always transition', + ], + ], + ], + 'states' => [ + 'child_a' => [ + 'type' => 'atomic', + ], + 'child_b' => [ + 'type' => 'final', + ], + ], + ], + 'state_b' => [], + 'state_c' => [], + ], + ]))->not->toThrow(exception: InvalidArgumentException::class); +}); From 276b314c21d71962711a206e4bb989cb57771298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:35:23 +0300 Subject: [PATCH 27/50] WB-784: test(stateconfigvalidator): add test for normalizing string behaviors Add a test to ensure string behaviors like guards, actions, and calculators are normalized to arrays without throwing exceptions. --- tests/StateConfigValidatorTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index a08dd1f..31b84da 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -217,3 +217,22 @@ ], ]))->not->toThrow(exception: InvalidArgumentException::class); }); + +test('normalizes string behaviors to arrays', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'guards' => 'singleGuard', + 'actions' => 'singleAction', + 'calculators' => 'singleCalculator', + ], + ], + ], + ], + ]))->not->toThrow(exception: InvalidArgumentException::class); +}); + From 34bfd47bea3f8b66dc46c6d386cafa1bc7c25651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:36:57 +0300 Subject: [PATCH 28/50] WB-784: test(stateconfigvalidator): add test for empty guarded transitions array Add test to ensure that an exception is thrown when a state has an empty conditions array for a guarded transition, improving validation coverage. --- tests/StateConfigValidatorTest.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 31b84da..d4cfaeb 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -236,3 +236,18 @@ ]))->not->toThrow(exception: InvalidArgumentException::class); }); +test('validates empty guarded transitions array', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [], // Empty conditions array + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has empty conditions array for event 'EVENT'. Guarded transitions must have at least one condition." + ); +}); From 99fd4db32b08fcfa36e429c50f576f74d4410c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:37:39 +0300 Subject: [PATCH 29/50] WB-784: test(stateconfigvalidator): add test for default condition order in guarded transitions Add test to validate that default conditions (no guards) must be the last in guarded transitions. --- tests/StateConfigValidatorTest.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index d4cfaeb..64a528c 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -251,3 +251,27 @@ exceptionMessage: "State 'state_a' has empty conditions array for event 'EVENT'. Guarded transitions must have at least one condition." ); }); + +test('validates default condition must be last in guarded transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + [ + 'target' => 'state_b', // Default condition (no guards) + ], + [ + 'target' => 'state_c', + 'guards' => 'someGuard', + ], + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid conditions order for event 'EVENT'. Default condition (no guards) must be the last condition." + ); +}); From 4e2ffaaeb76e4a0960107c1cadb621ca362b189b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:38:17 +0300 Subject: [PATCH 30/50] WB-784: test(stateconfigvalidator): add test for required target in guarded transitions Add a new test to validate that guarded transitions must specify a target. Throws `InvalidArgumentException` with a clear error message when the target is missing. --- tests/StateConfigValidatorTest.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 64a528c..e4f8cb7 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -275,3 +275,23 @@ exceptionMessage: "State 'state_a' has invalid conditions order for event 'EVENT'. Default condition (no guards) must be the last condition." ); }); + +test('validates target is required in guarded transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + [ + 'guards' => 'someGuard', // Missing target + ], + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid condition at index 0 for event 'EVENT'. Each condition must have a target." + ); +}); From 5a87027e47a6a09166739441e2218a8fbba6a840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:39:07 +0300 Subject: [PATCH 31/50] WB-784: test(state-config-validator): add test for valid guarded transitions Verify state machine accepts valid transitions with multiple conditions. --- tests/StateConfigValidatorTest.php | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index e4f8cb7..d009d2d 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -295,3 +295,30 @@ exceptionMessage: "State 'state_a' has invalid condition at index 0 for event 'EVENT'. Each condition must have a target." ); }); + +test('accepts valid guarded transitions with multiple conditions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + [ + 'target' => 'state_b', + 'guards' => ['guard1', 'guard2'], + 'actions' => 'action1', + 'calculators' => ['calc1', 'calc2'], + ], + [ + 'target' => 'state_c', + 'guards' => 'guard3', + ], + [ + 'target' => 'state_d', // Default condition + ], + ], + ], + ], + ], + ]))->not->toThrow(exception: InvalidArgumentException::class); +}); From 33c46f7b1526f36d5c19c60370c84c4f2b3c4b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:46:16 +0300 Subject: [PATCH 32/50] WB-784: fix(stateconfigvalidator): clarify error message for invalid actions configuration Improve error message to specify "entry/exit actions" for better clarity. --- src/StateConfigValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index d916b26..fb97cfc 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -208,7 +208,7 @@ private static function validateStateActions(array $stateConfig, string $path): $actions = $stateConfig[$actionType]; if (!is_string($actions) && !is_array($actions)) { throw new InvalidArgumentException( - message: "State '{$path}' has invalid {$actionType} actions configuration. ". + message: "State '{$path}' has invalid entry/exit actions configuration. ". 'Actions must be an array or string.' ); } From 390e8e37234463b537b87a154ee40f45dda6ad05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:46:42 +0300 Subject: [PATCH 33/50] WB-784: refactor(stateconfigvalidator): differentiate error labels for behaviors Update behavior labels for error messages to improve readability. --- src/StateConfigValidator.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index fb97cfc..f0ad859 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -300,16 +300,20 @@ private static function validateTransitionBehaviors( string $path, string $eventName ): void { - $behaviors = ['guards', 'actions', 'calculators']; + $behaviors = [ + 'guards' => 'Guards', + 'actions' => 'Actions', + 'calculators' => 'Calculators', + ]; - foreach ($behaviors as $behavior) { + foreach ($behaviors as $behavior => $label) { if (isset($transitionConfig[$behavior])) { try { - $transitionConfig[$behavior] = self::normalizeArrayOrString(value: $transitionConfig[$behavior]); + $transitionConfig[$behavior] = self::normalizeArrayOrString($transitionConfig[$behavior]); } catch (InvalidArgumentException) { throw new InvalidArgumentException( message: "State '{$path}' has invalid {$behavior} configuration for event '{$eventName}'. ". - "{$behavior} must be an array or string." + "{$label} must be an array or string." ); } } From db79265d958a7877a7509b332864433dcf93a919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:46:49 +0300 Subject: [PATCH 34/50] WB-784: fix(state-validator): improve condition validation error message Clarify error message for invalid conditions in state transitions, specifying required elements in the array (target/guards/actions). --- src/StateConfigValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index f0ad859..a7d6f4a 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -335,8 +335,8 @@ private static function validateGuardedTransitions(array $conditions, string $pa foreach ($conditions as $index => $condition) { if (!is_array($condition)) { throw new InvalidArgumentException( - message: "State '{$path}' has invalid condition at index {$index} for event '{$eventName}'. ". - 'Each condition must be an array.' + message: "State '{$path}' has invalid condition in transition for event '{$eventName}'. ". + 'Each condition must be an array with target/guards/actions.' ); } From 46a735ecac274cd416719b0b672f32db85410c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:47:40 +0300 Subject: [PATCH 35/50] WB-784: test(state-config-validator): add test for validating condition arrays in transitions Add a new test to ensure that transition conditions in state configurations are properly validated as arrays, throwing an exception for invalid formats. --- tests/StateConfigValidatorTest.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index d009d2d..12bae37 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -97,6 +97,26 @@ exceptionMessage: "State 'state_a' has invalid transition for event 'EVENT'. Transition must be a string (target state) or an array (transition config)." ); }); + +test('validates condition arrays in transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'not_an_array', // Invalid condition - should be an array + ['target' => 'state_b'], + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid condition in transition for event 'EVENT'. Each condition must be an array with target/guards/actions." + ); +}); test('validates allowed keys in transition config', function (): void { expect(fn () => MachineDefinition::define([ 'id' => 'machine', From af085babbcd8ecd350afd0b5e159c8c5d80682f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:48:50 +0300 Subject: [PATCH 36/50] WB-784: test(stateconfigvalidator): add test for invalid actions configuration in transitions Add a new test case to validate that actions in transitions must be an array or string. Throws an exception for invalid configurations. --- tests/StateConfigValidatorTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 12bae37..4a0ea79 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -117,6 +117,25 @@ exceptionMessage: "State 'state_a' has invalid condition in transition for event 'EVENT'. Each condition must be an array with target/guards/actions." ); }); +test('validates actions configuration in transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'actions' => true, // Actions should be an array or string + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid actions configuration for event 'EVENT'. Actions must be an array or string." + ); +}); test('validates allowed keys in transition config', function (): void { expect(fn () => MachineDefinition::define([ 'id' => 'machine', From 735b6c6aa827aa32666aef53e5e2543b2fcfa340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:49:38 +0300 Subject: [PATCH 37/50] WB-784: test(stateconfigvalidator): add test for invalid calculators config Add a test case to verify that calculators in transitions must be an array or string. --- tests/StateConfigValidatorTest.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 4a0ea79..b0dca6f 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -136,6 +136,27 @@ exceptionMessage: "State 'state_a' has invalid actions configuration for event 'EVENT'. Actions must be an array or string." ); }); + +test('validates calculators configuration in transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'calculators' => 123, // Calculators should be an array or string + ], + ], + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid calculators configuration for event 'EVENT'. Calculators must be an array or string." + ); +}); + test('validates allowed keys in transition config', function (): void { expect(fn () => MachineDefinition::define([ 'id' => 'machine', From db5f470a39d53cc2dd12404a303b95944c01b75c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:50:23 +0300 Subject: [PATCH 38/50] WB-784: test(stateconfigvalidator): add test for validating entry/exit actions Ensure entry and exit actions in state configuration are arrays or strings, throwing an exception for invalid types. --- tests/StateConfigValidatorTest.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index b0dca6f..082a24d 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -229,6 +229,22 @@ ); }); +test('validates entry and exit actions are arrays or strings', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'entry' => true, // Should be an array or a string + 'exit' => 123, // Should be an array or a string + ], + ], + ]))->toThrow( + exception: InvalidArgumentException::class, + exceptionMessage: "State 'state_a' has invalid entry/exit actions configuration. Actions must be an array or string." + ); +}); + test('accepts valid state configuration with all possible features', function (): void { expect(fn () => MachineDefinition::define([ 'id' => 'machine', From 7e560c72b36a14e7af27d71387ca2eadf4018e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 22:55:36 +0300 Subject: [PATCH 39/50] WB-784: test(stateconfigvalidator): add test for invalid guards configuration Add a test to validate that guards in state transitions are properly configured as an array or string. Throws an exception for invalid configurations to ensure proper validation. --- src/StateConfigValidator.php | 2 +- tests/StateConfigValidatorTest.php | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index a7d6f4a..91fdb3f 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -309,7 +309,7 @@ private static function validateTransitionBehaviors( foreach ($behaviors as $behavior => $label) { if (isset($transitionConfig[$behavior])) { try { - $transitionConfig[$behavior] = self::normalizeArrayOrString($transitionConfig[$behavior]); + $transitionConfig[$behavior] = self::normalizeArrayOrString(value: $transitionConfig[$behavior]); } catch (InvalidArgumentException) { throw new InvalidArgumentException( message: "State '{$path}' has invalid {$behavior} configuration for event '{$eventName}'. ". diff --git a/tests/StateConfigValidatorTest.php b/tests/StateConfigValidatorTest.php index 082a24d..6ac52c4 100644 --- a/tests/StateConfigValidatorTest.php +++ b/tests/StateConfigValidatorTest.php @@ -117,6 +117,27 @@ exceptionMessage: "State 'state_a' has invalid condition in transition for event 'EVENT'. Each condition must be an array with target/guards/actions." ); }); + +test('validates guards configuration in transitions', function (): void { + expect(fn () => MachineDefinition::define([ + 'id' => 'machine', + 'initial' => 'state_a', + 'states' => [ + 'state_a' => [ + 'on' => [ + 'EVENT' => [ + 'target' => 'state_b', + 'guards' => true, // Guards should be an array or a string + ], + ], + ], + ], + ]))->toThrow( + InvalidArgumentException::class, + "State 'state_a' has invalid guards configuration for event 'EVENT'. Guards must be an array or string." + ); +}); + test('validates actions configuration in transitions', function (): void { expect(fn () => MachineDefinition::define([ 'id' => 'machine', From abe9843824b29b7faf1ed7ee62934a225592e760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 23:02:56 +0300 Subject: [PATCH 40/50] WB-784: feat(validator): add 'id' and 'result' to allowed state keys Expand the set of allowed state keys in `StateConfigValidator` to include 'id' and 'result', enabling additional configuration flexibility. --- src/StateConfigValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index 91fdb3f..ccedbe9 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -16,7 +16,7 @@ class StateConfigValidator ]; private const ALLOWED_STATE_KEYS = [ - 'on', 'states', 'initial', 'type', 'meta', 'entry', 'exit', 'description', + 'id', 'on', 'states', 'initial', 'type', 'meta', 'entry', 'exit', 'description', 'result', ]; private const ALLOWED_TRANSITION_KEYS = [ From 8a3a3102be57b49018954dd0290795510916e315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 23:03:02 +0300 Subject: [PATCH 41/50] WB-784: test(state): remove tests for invalid final state definitions These tests were removed as the associated validation for final state definitions is no longer necessary or applicable. --- tests/StateDefinitionTypeTest.php | 39 ------------------------------- 1 file changed, 39 deletions(-) diff --git a/tests/StateDefinitionTypeTest.php b/tests/StateDefinitionTypeTest.php index 6a1c8ef..4a8301a 100644 --- a/tests/StateDefinitionTypeTest.php +++ b/tests/StateDefinitionTypeTest.php @@ -9,7 +9,6 @@ use Tarfinlabs\EventMachine\Enums\StateDefinitionType; use Tarfinlabs\EventMachine\Definition\MachineDefinition; use Tarfinlabs\EventMachine\Tests\Stubs\Results\GreenResult; -use Tarfinlabs\EventMachine\Exceptions\InvalidFinalStateDefinitionException; test('a state definition can be atomic', function (): void { $machine = MachineDefinition::define(config: [ @@ -96,44 +95,6 @@ '@green', ]); -test('a final state definition can not have child states', function (): void { - MachineDefinition::define(config: [ - 'initial' => 'yellow', - 'states' => [ - 'yellow' => [ - 'type' => 'final', - 'states' => [ - 'a' => [], - 'b' => [], - ], - ], - ], - ]); -})->throws( - exception: InvalidFinalStateDefinitionException::class, - exceptionMessage: 'The final state `machine.yellow` should not have child states. Please revise your state machine definitions to ensure that final states are correctly configured without child states.' -); - -test('a final state definition can not have transitions', function (): void { - MachineDefinition::define(config: [ - 'initial' => 'yellow', - 'states' => [ - 'yellow' => [ - 'type' => 'final', - 'on' => [ - 'EVENT' => [ - 'target' => 'red', - ], - ], - ], - 'red' => [], - ], - ]); -})->throws( - exception: InvalidFinalStateDefinitionException::class, - exceptionMessage: 'The final state `machine.yellow` should not have transitions. Check your state machine configuration to ensure events are not dispatched when in a final state.' -); - test('an initial state of type final triggers machine finish event', function (): void { $machine = Machine::create(definition: [ 'config' => [ From 0d8c68f70079459a8b6365f44783906e8266e28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Thu, 12 Dec 2024 23:04:12 +0300 Subject: [PATCH 42/50] WB-784: fix(tests): simplify StateDefinitionTypeTest result callback Remove unnecessary parameters from the 'result' callback in the StateDefinitionTypeTest to simplify the test logic and ensure compatibility with current use cases. --- tests/StateDefinitionTypeTest.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/StateDefinitionTypeTest.php b/tests/StateDefinitionTypeTest.php index 4a8301a..28a5c7e 100644 --- a/tests/StateDefinitionTypeTest.php +++ b/tests/StateDefinitionTypeTest.php @@ -4,8 +4,6 @@ use Illuminate\Support\Carbon; use Tarfinlabs\EventMachine\Actor\Machine; -use Tarfinlabs\EventMachine\ContextManager; -use Tarfinlabs\EventMachine\Behavior\EventBehavior; use Tarfinlabs\EventMachine\Enums\StateDefinitionType; use Tarfinlabs\EventMachine\Definition\MachineDefinition; use Tarfinlabs\EventMachine\Tests\Stubs\Results\GreenResult; @@ -72,7 +70,7 @@ ], 'yellow' => [ 'type' => 'final', - 'result' => function (ContextManager $context, EventBehavior $event): Carbon { + 'result' => function (): Carbon { return now(); }, ], From 1bb89576ff52fdf46e64b9fb3612a08fb718a01e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:36:04 +0300 Subject: [PATCH 43/50] WB-784: fix(state-config-validator): consolidate default condition validation Simplify logic for validating default condition order, ensuring proper error handling for improperly ordered conditions with no guards. --- src/StateConfigValidator.php | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/StateConfigValidator.php b/src/StateConfigValidator.php index ccedbe9..c398c86 100644 --- a/src/StateConfigValidator.php +++ b/src/StateConfigValidator.php @@ -347,17 +347,12 @@ private static function validateGuardedTransitions(array $conditions, string $pa ); } - // Check if this is a default condition (no guards) - $isDefaultCondition = !isset($condition['guards']); - - if ($isDefaultCondition) { - // If this is not the last condition - if ($index !== count($conditions) - 1) { - throw new InvalidArgumentException( - message: "State '{$path}' has invalid conditions order for event '{$eventName}'. ". - 'Default condition (no guards) must be the last condition.' - ); - } + // If this is not the last condition + if (!isset($condition['guards']) && $index !== count($conditions) - 1) { + throw new InvalidArgumentException( + message: "State '{$path}' has invalid conditions order for event '{$eventName}'. ". + 'Default condition (no guards) must be the last condition.' + ); } } } From e62d300ba0bbd891651d0c3eb90a41e34c1bb744 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:36:12 +0300 Subject: [PATCH 44/50] WB-784: fix(machine-definition): remove unused parameter in validation Remove `$this->id` from `StateConfigValidator::validate` call as it is not utilized. This refactor ensures cleaner code and prevents potential confusion. --- 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 dfa8305..2f9bea5 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -85,7 +85,7 @@ private function __construct( public ?array $scenarios, public string $delimiter = self::STATE_DELIMITER, ) { - StateConfigValidator::validate($config, $this->id); + StateConfigValidator::validate($config); $this->scenariosEnabled = isset($this->config['scenarios_enabled']) && $this->config['scenarios_enabled'] === true; From 124ef5e0abf0d787acb60059485c45f6d37fa6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:42:53 +0300 Subject: [PATCH 45/50] WB-784: fix(machine-definition): reorder condition check to prevent errors Reorder `isset` and `has` condition evaluation to ensure proper logical flow and avoid potential issues with undefined keys in `idMap`. --- 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 2f9bea5..a89ebe0 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -298,7 +298,7 @@ public function getScenarioStateIfAvailable(State $state, EventBehavior|array|nu } $scenarioStateKey = str_replace($this->id, $this->id.$this->delimiter.$state->context->get('scenarioType'), $state->currentStateDefinition->id); - if ($state->context->has('scenarioType') && isset($this->idMap[$scenarioStateKey])) { + if (isset($this->idMap[$scenarioStateKey]) && $state->context->has('scenarioType')) { return $state->setCurrentStateDefinition(stateDefinition: $this->idMap[$scenarioStateKey]); } From 9b5281e9990142986735416e126dc85c4889a7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:43:08 +0300 Subject: [PATCH 46/50] WB-784: feat(definition): support InvokableBehavior in return type Update `getInvokableBehavior` method to include `InvokableBehavior` in return type, enhancing type safety and clarity. --- src/Definition/MachineDefinition.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Definition/MachineDefinition.php b/src/Definition/MachineDefinition.php index a89ebe0..c0ce5be 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -403,9 +403,9 @@ public function setupContextManager(): void * @param string $behaviorDefinition The behavior definition to look up. * @param BehaviorType $behaviorType The type of the behavior (e.g., guard or action). * - * @return callable|null The invokable behavior instance or callable, or null if not found. + * @return callable|\Tarfinlabs\EventMachine\Behavior\InvokableBehavior|null The invokable behavior instance or callable, or null if not found. */ - public function getInvokableBehavior(string $behaviorDefinition, BehaviorType $behaviorType): ?callable + public function getInvokableBehavior(string $behaviorDefinition, BehaviorType $behaviorType): null|callable|InvokableBehavior { // If the guard definition is an invokable GuardBehavior, create a new instance. if (is_subclass_of($behaviorDefinition, InvokableBehavior::class)) { From cb45d571d0c6c9e3fb90632f6a83f54fc7db5e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:43:15 +0300 Subject: [PATCH 47/50] WB-784: fix(machine-definition): correct parameter passed to getScenarioStateIfAvailable Adjust parameter name from `eventBehavior` to `event` in method call to ensure accurate functionality. --- 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 c0ce5be..b74dd53 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -224,7 +224,7 @@ public function getInitialState(EventBehavior|array|null $event = null): ?State currentStateDefinition: $this->initialStateDefinition, ); - $initialState = $this->getScenarioStateIfAvailable(state: $initialState, eventBehavior: $eventBehavior ?? null); + $initialState = $this->getScenarioStateIfAvailable(state: $initialState, eventBehavior: $event ?? null); $this->initialStateDefinition = $initialState->currentStateDefinition; // Record the internal machine init event. From 7f0613fae37ad031fb0b628db7cd77b7c9b7f282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:43:26 +0300 Subject: [PATCH 48/50] WB-784: fix(machine-definition): correct null safe operator usage Fixes improper use of null safe operator when comparing state IDs. Prevents potential logic issues in machine state transitions. --- 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 b74dd53..74f1e07 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -633,7 +633,7 @@ public function transition( // Get scenario state if exists $newState = $this->getScenarioStateIfAvailable(state: $newState, eventBehavior: $eventBehavior); - if ($targetStateDefinition !== null && $targetStateDefinition?->id !== $newState->currentStateDefinition->id) { + if ($targetStateDefinition !== null && $targetStateDefinition->id !== $newState->currentStateDefinition->id) { $targetStateDefinition = $newState->currentStateDefinition; } From 3ada833222c69406873d08342e514bce8a709d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:44:08 +0300 Subject: [PATCH 49/50] WB-784: fix(definition): use static method call for context validation Ensure correct invocation of validateRequiredContext using the static method call, resolving potential issues with method resolution and adherence to coding standards. --- 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 74f1e07..a1264ee 100644 --- a/src/Definition/MachineDefinition.php +++ b/src/Definition/MachineDefinition.php @@ -724,7 +724,7 @@ public function runAction( ); if ($actionBehavior instanceof InvokableBehavior) { - $actionBehavior->validateRequiredContext($state->context); + $actionBehavior::validateRequiredContext($state->context); } // Get the number of events in the queue before the action is executed. From 9b2181abf3c87e09a464bcf49260b234321a9554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Emre=20Delig=C3=B6z?= Date: Fri, 13 Dec 2024 09:44:19 +0300 Subject: [PATCH 50/50] WB-784: fix(transition): call validateRequiredContext statically in GuardBehavior Update `validateRequiredContext` to be called statically to align with correct usage and avoid potential runtime errors. --- src/Definition/TransitionDefinition.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Definition/TransitionDefinition.php b/src/Definition/TransitionDefinition.php index 86d565d..020f011 100644 --- a/src/Definition/TransitionDefinition.php +++ b/src/Definition/TransitionDefinition.php @@ -167,7 +167,7 @@ public function getFirstValidTransitionBranch( $shouldLog = $guardBehavior?->shouldLog ?? false; if ($guardBehavior instanceof GuardBehavior) { - $guardBehavior->validateRequiredContext($state->context); + $guardBehavior::validateRequiredContext($state->context); } // Inject guard behavior parameters