Skip to content

Commit 93053e6

Browse files
author
sd-lueckel
authored
Merge pull request #5 from solutionDrive/feature/MAIN-117-extend-multistep-configuration
Feature/main 117 extend multistep configuration
2 parents 5c73f82 + a7b41f2 commit 93053e6

13 files changed

Lines changed: 192 additions & 17 deletions

spec/Context/FlowContextSpec.php

Lines changed: 70 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use solutionDrive\MultiStepBundle\Context\FlowContextInterface;
1616
use solutionDrive\MultiStepBundle\Model\MultiStepFlowInterface;
1717
use solutionDrive\MultiStepBundle\Model\MultiStepInterface;
18+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
1819

1920
class FlowContextSpec extends ObjectBehavior
2021
{
@@ -39,26 +40,82 @@ public function it_returns_current_step(MultiStepInterface $currentStep): void
3940
$this->getCurrentStep()->shouldBe($currentStep);
4041
}
4142

42-
public function it_returns_next_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
43-
{
43+
public function it_returns_direct_successor_as_next_step(
44+
MultiStepFlowInterface $flow,
45+
MultiStepInterface $nextStep,
46+
StepRequiredCheckerInterface $stepRequiredChecker
47+
): void {
48+
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
49+
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
4450
$flow->getStepAfter(Argument::any())->shouldBeCalled()->willReturn($nextStep);
4551
$this->getNextStep()->shouldBe($nextStep);
4652
}
4753

48-
public function it_returns_previous_step(MultiStepFlowInterface $flow, MultiStepInterface $previousStep): void
54+
public function it_returns_step_after_successor_as_next_step(
55+
MultiStepFlowInterface $flow,
56+
MultiStepInterface $currentStep,
57+
MultiStepInterface $nextStep,
58+
MultiStepInterface $nextStepAfter,
59+
StepRequiredCheckerInterface $stepRequiredCheckerNext,
60+
StepRequiredCheckerInterface $stepRequiredCheckerAfterNext
61+
): void {
62+
63+
$stepRequiredCheckerNext->check()->shouldBeCalled()->willReturn(false);
64+
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredCheckerNext);
65+
66+
$stepRequiredCheckerAfterNext->check()->shouldBeCalled()->willReturn(true);
67+
$nextStepAfter->getStepRequiredChecker()->willReturn($stepRequiredCheckerAfterNext);
68+
69+
$flow->getStepAfter($currentStep)->shouldBeCalled()->willReturn($nextStep);
70+
$flow->getStepAfter($nextStep)->shouldBeCalled()->willReturn($nextStepAfter);
71+
$this->getNextStep()->shouldBe($nextStepAfter);
72+
}
73+
74+
public function it_returns_direct_predecessor_previous_step(
75+
MultiStepFlowInterface $flow,
76+
MultiStepInterface $previousStep,
77+
StepRequiredCheckerInterface $stepRequiredChecker
78+
): void
4979
{
80+
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
81+
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
5082
$flow->getStepBefore(Argument::any())->shouldBeCalled()->willReturn($previousStep);
5183
$this->getPreviousStep()->shouldBe($previousStep);
5284
}
5385

86+
public function it_returns_step_before_predecessor_as_previous_step(
87+
MultiStepFlowInterface $flow,
88+
MultiStepInterface $currentStep,
89+
MultiStepInterface $previousStep,
90+
MultiStepInterface $prviousStepBefore,
91+
StepRequiredCheckerInterface $stepRequiredCheckerPrevious,
92+
StepRequiredCheckerInterface $stepRequiredCheckerBeforePrevious
93+
): void {
94+
95+
$stepRequiredCheckerPrevious->check()->shouldBeCalled()->willReturn(false);
96+
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredCheckerPrevious);
97+
98+
$stepRequiredCheckerBeforePrevious->check()->shouldBeCalled()->willReturn(true);
99+
$prviousStepBefore->getStepRequiredChecker()->willReturn($stepRequiredCheckerBeforePrevious);
100+
101+
$flow->getStepBefore($currentStep)->shouldBeCalled()->willReturn($previousStep);
102+
$flow->getStepBefore($previousStep)->shouldBeCalled()->willReturn($prviousStepBefore);
103+
$this->getPreviousStep()->shouldBe($prviousStepBefore);
104+
}
105+
54106
public function it_returns_false_for_has_next_step(MultiStepFlowInterface $flow): void
55107
{
56108
$flow->getStepAfter(Argument::any())->willReturn(null);
57109
$this->hasNextStep()->shouldBe(false);
58110
}
59111

60-
public function it_returns_true_for_has_next_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
61-
{
112+
public function it_returns_true_for_has_next_step(
113+
MultiStepFlowInterface $flow,
114+
MultiStepInterface $nextStep,
115+
StepRequiredCheckerInterface $stepRequiredChecker
116+
): void {
117+
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
118+
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
62119
$flow->getStepAfter(Argument::any())->willReturn($nextStep);
63120
$this->hasNextStep()->shouldBe(true);
64121
}
@@ -69,9 +126,14 @@ public function it_returns_false_for_has_previous_step(MultiStepFlowInterface $f
69126
$this->hasPreviousStep()->shouldBe(false);
70127
}
71128

72-
public function it_returns_true_for_has_previous_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
73-
{
74-
$flow->getStepBefore(Argument::any())->willReturn($nextStep);
129+
public function it_returns_true_for_has_previous_step(
130+
MultiStepFlowInterface $flow,
131+
MultiStepInterface $previousStep,
132+
StepRequiredCheckerInterface $stepRequiredChecker
133+
): void {
134+
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
135+
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
136+
$flow->getStepBefore(Argument::any())->willReturn($previousStep);
75137
$this->hasPreviousStep()->shouldBe(true);
76138
}
77139

spec/Factory/MultiStepFactorySpec.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use PhpSpec\ObjectBehavior;
1313
use solutionDrive\MultiStepBundle\Factory\MultiStepFactory;
14+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
1415

1516
class MultiStepFactorySpec extends ObjectBehavior
1617
{
@@ -19,13 +20,14 @@ function it_is_initializable()
1920
$this->shouldBeAnInstanceOf(MultiStepFactory::class);
2021
}
2122

22-
function it_can_create_step()
23+
function it_can_create_step(StepRequiredCheckerInterface $stepRequiredChecker)
2324
{
2425
$config = [
25-
'alias' => 'TestAlias',
26-
'slug' => 'TestSlug',
27-
'template' => 'TestTemplate',
28-
'controller' => 'TestController',
26+
'alias' => 'TestAlias',
27+
'slug' => 'TestSlug',
28+
'template' => 'TestTemplate',
29+
'controller' => 'TestController',
30+
'stepRequiredChecker' => $stepRequiredChecker
2931
];
3032

3133
$step = $this->createFromConfig('test_id', $config);
@@ -34,5 +36,6 @@ function it_can_create_step()
3436
$step->getSlug()->shouldReturn('TestSlug');
3537
$step->getTemplate()->shouldReturn('TestTemplate');
3638
$step->getControllerAction()->shouldReturn('TestController');
39+
$step->getStepRequiredChecker()->shouldReturn($stepRequiredChecker);
3740
}
3841
}

spec/Model/MultiStepSpec.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use PhpSpec\ObjectBehavior;
1313
use solutionDrive\MultiStepBundle\Model\MultiStep;
1414
use solutionDrive\MultiStepBundle\Model\MultiStepInterface;
15+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
1516

1617
final class MultiStepSpec extends ObjectBehavior
1718
{
@@ -59,4 +60,10 @@ function it_has_controller_action()
5960
$this->setControllerAction($value);
6061
$this->getControllerAction()->shouldReturn($value);
6162
}
63+
64+
function it_has_step_required_checker(StepRequiredCheckerInterface $stepRequiredChecker)
65+
{
66+
$this->setStepRequiredChecker($stepRequiredChecker);
67+
$this->getStepRequiredChecker()->shouldBe($stepRequiredChecker);
68+
}
6269
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace spec\solutionDrive\MultiStepBundle\StepChecker;
4+
5+
use PhpSpec\ObjectBehavior;
6+
use solutionDrive\MultiStepBundle\StepChecker\DefaultStepRequiredChecker;
7+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
8+
9+
class DefaultStepRequiredCheckerSpec extends ObjectBehavior
10+
{
11+
function it_is_initializable()
12+
{
13+
$this->shouldHaveType(DefaultStepRequiredChecker::class);
14+
}
15+
16+
function it_implements_step_required_checker_interface()
17+
{
18+
$this->shouldImplement(StepRequiredCheckerInterface::class);
19+
}
20+
21+
function it_returns_true()
22+
{
23+
$this->check()->shouldReturn(true);
24+
}
25+
}

src/Context/FlowContext.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,23 @@ public function getCurrentStep(): MultiStepInterface
3434
public function getNextStep(): ?MultiStepInterface
3535
{
3636
$currentStep = $this->getCurrentStep();
37-
return $this->flow->getStepAfter($currentStep);
37+
do {
38+
$nextStep = $this->flow->getStepAfter($currentStep);
39+
$currentStep = $nextStep;
40+
} while (null !== $nextStep && false === $nextStep->getStepRequiredChecker()->check());
41+
42+
return $nextStep;
3843
}
3944

4045
public function getPreviousStep(): ?MultiStepInterface
4146
{
4247
$currentStep = $this->getCurrentStep();
43-
return $this->flow->getStepBefore($currentStep);
48+
do {
49+
$previousStep = $this->flow->getStepBefore($currentStep);
50+
$currentStep = $previousStep;
51+
} while (null !== $previousStep && false === $previousStep->getStepRequiredChecker()->check());
52+
53+
return $previousStep;
4454
}
4555

4656
public function hasNextStep(): bool

src/DependencyInjection/Configuration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public function getConfigTreeBuilder()
3939
'solutionDrive\MultiStepBundle\Controller\DefaultStepController::renderAction'
4040
)
4141
->end()
42+
->scalarNode('stepRequiredChecker')
43+
->defaultValue('sd.multistep.step_checker.default')
44+
->end()
4245
->end()
4346
->end()
4447
->end()

src/DependencyInjection/MultiStepExtension.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Symfony\Component\Config\FileLocator;
1313
use Symfony\Component\DependencyInjection\ContainerBuilder;
1414
use Symfony\Component\DependencyInjection\Loader;
15+
use Symfony\Component\DependencyInjection\Reference;
1516
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
1617

1718
class MultiStepExtension extends Extension
@@ -38,8 +39,14 @@ public function load(array $configs, ContainerBuilder $container)
3839
private function parseFlows(array $flowsArray, ContainerBuilder $container): void
3940
{
4041
$registryDefinition = $container->getDefinition('sd.multistep.flow_registry');
41-
foreach ($flowsArray as $id => $config) {
42-
$registryDefinition->addMethodCall('addByConfig', [$id, $config]);
42+
foreach ($flowsArray as $id => $flowConfig) {
43+
$flowConfig['steps'] = array_map(function (array $options): array {
44+
if (isset($options['stepRequiredChecker'])) {
45+
$options['stepRequiredChecker'] = new Reference($options['stepRequiredChecker']);
46+
}
47+
return $options;
48+
}, $flowConfig['steps']);
49+
$registryDefinition->addMethodCall('addByConfig', [$id, $flowConfig]);
4350
}
4451
}
4552
}

src/Factory/MultiStepFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function createFromConfig(string $id, array $config): MultiStepInterface
2626
$step->setSlug($config['slug']);
2727
$step->setTemplate($config['template']);
2828
$step->setControllerAction($config['controller']);
29+
$step->setStepRequiredChecker($config['stepRequiredChecker']);
2930
return $step;
3031
}
3132
}

src/Model/MultiStep.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
namespace solutionDrive\MultiStepBundle\Model;
1111

12+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
13+
1214
class MultiStep implements MultiStepInterface
1315
{
1416
/** @var string */
@@ -26,6 +28,9 @@ class MultiStep implements MultiStepInterface
2628
/** @var string */
2729
private $controllerAction = '';
2830

31+
/** @var StepRequiredCheckerInterface */
32+
private $stepRequiredChecker;
33+
2934
public function getId(): string
3035
{
3136
return $this->id;
@@ -75,4 +80,14 @@ public function setControllerAction(string $controllerAction): void
7580
{
7681
$this->controllerAction = $controllerAction;
7782
}
83+
84+
public function getStepRequiredChecker(): StepRequiredCheckerInterface
85+
{
86+
return $this->stepRequiredChecker;
87+
}
88+
89+
public function setStepRequiredChecker(StepRequiredCheckerInterface $stepRequiredChecker): void
90+
{
91+
$this->stepRequiredChecker = $stepRequiredChecker;
92+
}
7893
}

src/Model/MultiStepInterface.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace solutionDrive\MultiStepBundle\Model;
1010

11+
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;
12+
1113
interface MultiStepInterface
1214
{
1315
public function getId(): string;
@@ -29,4 +31,8 @@ public function setTemplate(string $slug): void;
2931
public function getControllerAction(): string;
3032

3133
public function setControllerAction(string $controllerAction): void;
34+
35+
public function getStepRequiredChecker(): StepRequiredCheckerInterface;
36+
37+
public function setStepRequiredChecker(StepRequiredCheckerInterface $stepRequiredChecker): void;
3238
}

0 commit comments

Comments
 (0)