diff --git a/mailpoet/lib/Automation/Engine/Validation/WorkflowRules/NoJoinRule.php b/mailpoet/lib/Automation/Engine/Validation/WorkflowRules/NoJoinRule.php new file mode 100644 index 0000000000..ef552a201b --- /dev/null +++ b/mailpoet/lib/Automation/Engine/Validation/WorkflowRules/NoJoinRule.php @@ -0,0 +1,32 @@ + */ + private $visitedSteps = []; + + public function initialize(Workflow $workflow): void { + $this->visitedSteps = []; + } + + public function visitNode(Workflow $workflow, WorkflowNode $node): void { + $step = $node->getStep(); + $this->visitedSteps[$step->getId()] = $step; + foreach ($step->getNextSteps() as $nextStep) { + $nextStepId = $nextStep->getId(); + if (isset($this->visitedSteps[$nextStepId])) { + throw Exceptions::workflowStructureNotValid(__('Path join found in workflow graph', 'mailpoet')); + } + } + } + + public function complete(Workflow $workflow): void { + } +} diff --git a/mailpoet/tests/unit/Automation/Engine/Validation/WorkflowRules/NoJoinRuleTest.php b/mailpoet/tests/unit/Automation/Engine/Validation/WorkflowRules/NoJoinRuleTest.php new file mode 100644 index 0000000000..c5e9658861 --- /dev/null +++ b/mailpoet/tests/unit/Automation/Engine/Validation/WorkflowRules/NoJoinRuleTest.php @@ -0,0 +1,73 @@ +createWorkflow([ + 'root' => ['a1', 'a2'], + 'a1' => ['b'], + 'a2' => ['b'], + 'b' => [], + ]); + + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Invalid workflow structure: Path join found in workflow graph'); + (new WorkflowWalker())->walk($workflow, [new NoJoinRule()]); + } + + public function testItDetectsLongJoinedPath(): void { + $workflow = $this->createWorkflow([ + 'root' => ['a1', 'a2'], + 'a1' => ['b1'], + 'a2' => ['b2'], + 'b1' => ['c1'], + 'b2' => ['c2'], + 'c1' => ['d'], + 'c2' => ['d'], + 'd' => [], + ]); + + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Invalid workflow structure: Path join found in workflow graph'); + (new WorkflowWalker())->walk($workflow, [new NoJoinRule()]); + } + + public function testItDetectsJoinedPathToSelf(): void { + $workflow = $this->createWorkflow([ + 'root' => ['root', 'root'], + ]); + + $this->expectException(UnexpectedValueException::class); + $this->expectExceptionMessage('Invalid workflow structure: Path join found in workflow graph'); + (new WorkflowWalker())->walk($workflow, [new NoJoinRule()]); + } + + public function testItPassesWithSimplePath(): void { + $workflow = $this->createWorkflow([ + 'root' => ['a'], + 'a' => ['b'], + 'b' => ['c'], + 'c' => [], + ]); + + (new WorkflowWalker())->walk($workflow, [new NoJoinRule()]); + // no exception thrown + } + + public function testItPassesWithPathSplit(): void { + $workflow = $this->createWorkflow([ + 'root' => ['a1', 'a1'], + 'a1' => [], + 'a2' => [], + ]); + + (new WorkflowWalker())->walk($workflow, [new NoJoinRule()]); + // no exception thrown + } +}