Skip to content

Commit

Permalink
Merge pull request #5 from solutionDrive/feature/MAIN-117-extend-mult…
Browse files Browse the repository at this point in the history
…istep-configuration

Feature/main 117 extend multistep configuration
  • Loading branch information
sd-lueckel authored Apr 10, 2018
2 parents 5c73f82 + a7b41f2 commit 93053e6
Show file tree
Hide file tree
Showing 13 changed files with 192 additions and 17 deletions.
78 changes: 70 additions & 8 deletions spec/Context/FlowContextSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use solutionDrive\MultiStepBundle\Context\FlowContextInterface;
use solutionDrive\MultiStepBundle\Model\MultiStepFlowInterface;
use solutionDrive\MultiStepBundle\Model\MultiStepInterface;
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

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

public function it_returns_next_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
{
public function it_returns_direct_successor_as_next_step(
MultiStepFlowInterface $flow,
MultiStepInterface $nextStep,
StepRequiredCheckerInterface $stepRequiredChecker
): void {
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
$flow->getStepAfter(Argument::any())->shouldBeCalled()->willReturn($nextStep);
$this->getNextStep()->shouldBe($nextStep);
}

public function it_returns_previous_step(MultiStepFlowInterface $flow, MultiStepInterface $previousStep): void
public function it_returns_step_after_successor_as_next_step(
MultiStepFlowInterface $flow,
MultiStepInterface $currentStep,
MultiStepInterface $nextStep,
MultiStepInterface $nextStepAfter,
StepRequiredCheckerInterface $stepRequiredCheckerNext,
StepRequiredCheckerInterface $stepRequiredCheckerAfterNext
): void {

$stepRequiredCheckerNext->check()->shouldBeCalled()->willReturn(false);
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredCheckerNext);

$stepRequiredCheckerAfterNext->check()->shouldBeCalled()->willReturn(true);
$nextStepAfter->getStepRequiredChecker()->willReturn($stepRequiredCheckerAfterNext);

$flow->getStepAfter($currentStep)->shouldBeCalled()->willReturn($nextStep);
$flow->getStepAfter($nextStep)->shouldBeCalled()->willReturn($nextStepAfter);
$this->getNextStep()->shouldBe($nextStepAfter);
}

public function it_returns_direct_predecessor_previous_step(
MultiStepFlowInterface $flow,
MultiStepInterface $previousStep,
StepRequiredCheckerInterface $stepRequiredChecker
): void
{
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
$flow->getStepBefore(Argument::any())->shouldBeCalled()->willReturn($previousStep);
$this->getPreviousStep()->shouldBe($previousStep);
}

public function it_returns_step_before_predecessor_as_previous_step(
MultiStepFlowInterface $flow,
MultiStepInterface $currentStep,
MultiStepInterface $previousStep,
MultiStepInterface $prviousStepBefore,
StepRequiredCheckerInterface $stepRequiredCheckerPrevious,
StepRequiredCheckerInterface $stepRequiredCheckerBeforePrevious
): void {

$stepRequiredCheckerPrevious->check()->shouldBeCalled()->willReturn(false);
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredCheckerPrevious);

$stepRequiredCheckerBeforePrevious->check()->shouldBeCalled()->willReturn(true);
$prviousStepBefore->getStepRequiredChecker()->willReturn($stepRequiredCheckerBeforePrevious);

$flow->getStepBefore($currentStep)->shouldBeCalled()->willReturn($previousStep);
$flow->getStepBefore($previousStep)->shouldBeCalled()->willReturn($prviousStepBefore);
$this->getPreviousStep()->shouldBe($prviousStepBefore);
}

public function it_returns_false_for_has_next_step(MultiStepFlowInterface $flow): void
{
$flow->getStepAfter(Argument::any())->willReturn(null);
$this->hasNextStep()->shouldBe(false);
}

public function it_returns_true_for_has_next_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
{
public function it_returns_true_for_has_next_step(
MultiStepFlowInterface $flow,
MultiStepInterface $nextStep,
StepRequiredCheckerInterface $stepRequiredChecker
): void {
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
$nextStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
$flow->getStepAfter(Argument::any())->willReturn($nextStep);
$this->hasNextStep()->shouldBe(true);
}
Expand All @@ -69,9 +126,14 @@ public function it_returns_false_for_has_previous_step(MultiStepFlowInterface $f
$this->hasPreviousStep()->shouldBe(false);
}

public function it_returns_true_for_has_previous_step(MultiStepFlowInterface $flow, MultiStepInterface $nextStep): void
{
$flow->getStepBefore(Argument::any())->willReturn($nextStep);
public function it_returns_true_for_has_previous_step(
MultiStepFlowInterface $flow,
MultiStepInterface $previousStep,
StepRequiredCheckerInterface $stepRequiredChecker
): void {
$stepRequiredChecker->check()->shouldBeCalled()->willReturn(true);
$previousStep->getStepRequiredChecker()->willReturn($stepRequiredChecker);
$flow->getStepBefore(Argument::any())->willReturn($previousStep);
$this->hasPreviousStep()->shouldBe(true);
}

Expand Down
13 changes: 8 additions & 5 deletions spec/Factory/MultiStepFactorySpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use PhpSpec\ObjectBehavior;
use solutionDrive\MultiStepBundle\Factory\MultiStepFactory;
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

class MultiStepFactorySpec extends ObjectBehavior
{
Expand All @@ -19,13 +20,14 @@ function it_is_initializable()
$this->shouldBeAnInstanceOf(MultiStepFactory::class);
}

function it_can_create_step()
function it_can_create_step(StepRequiredCheckerInterface $stepRequiredChecker)
{
$config = [
'alias' => 'TestAlias',
'slug' => 'TestSlug',
'template' => 'TestTemplate',
'controller' => 'TestController',
'alias' => 'TestAlias',
'slug' => 'TestSlug',
'template' => 'TestTemplate',
'controller' => 'TestController',
'stepRequiredChecker' => $stepRequiredChecker
];

$step = $this->createFromConfig('test_id', $config);
Expand All @@ -34,5 +36,6 @@ function it_can_create_step()
$step->getSlug()->shouldReturn('TestSlug');
$step->getTemplate()->shouldReturn('TestTemplate');
$step->getControllerAction()->shouldReturn('TestController');
$step->getStepRequiredChecker()->shouldReturn($stepRequiredChecker);
}
}
7 changes: 7 additions & 0 deletions spec/Model/MultiStepSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PhpSpec\ObjectBehavior;
use solutionDrive\MultiStepBundle\Model\MultiStep;
use solutionDrive\MultiStepBundle\Model\MultiStepInterface;
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

final class MultiStepSpec extends ObjectBehavior
{
Expand Down Expand Up @@ -59,4 +60,10 @@ function it_has_controller_action()
$this->setControllerAction($value);
$this->getControllerAction()->shouldReturn($value);
}

function it_has_step_required_checker(StepRequiredCheckerInterface $stepRequiredChecker)
{
$this->setStepRequiredChecker($stepRequiredChecker);
$this->getStepRequiredChecker()->shouldBe($stepRequiredChecker);
}
}
25 changes: 25 additions & 0 deletions spec/StepChecker/DefaultStepRequiredCheckerSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace spec\solutionDrive\MultiStepBundle\StepChecker;

use PhpSpec\ObjectBehavior;
use solutionDrive\MultiStepBundle\StepChecker\DefaultStepRequiredChecker;
use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

class DefaultStepRequiredCheckerSpec extends ObjectBehavior
{
function it_is_initializable()
{
$this->shouldHaveType(DefaultStepRequiredChecker::class);
}

function it_implements_step_required_checker_interface()
{
$this->shouldImplement(StepRequiredCheckerInterface::class);
}

function it_returns_true()
{
$this->check()->shouldReturn(true);
}
}
14 changes: 12 additions & 2 deletions src/Context/FlowContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,23 @@ public function getCurrentStep(): MultiStepInterface
public function getNextStep(): ?MultiStepInterface
{
$currentStep = $this->getCurrentStep();
return $this->flow->getStepAfter($currentStep);
do {
$nextStep = $this->flow->getStepAfter($currentStep);
$currentStep = $nextStep;
} while (null !== $nextStep && false === $nextStep->getStepRequiredChecker()->check());

return $nextStep;
}

public function getPreviousStep(): ?MultiStepInterface
{
$currentStep = $this->getCurrentStep();
return $this->flow->getStepBefore($currentStep);
do {
$previousStep = $this->flow->getStepBefore($currentStep);
$currentStep = $previousStep;
} while (null !== $previousStep && false === $previousStep->getStepRequiredChecker()->check());

return $previousStep;
}

public function hasNextStep(): bool
Expand Down
3 changes: 3 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ public function getConfigTreeBuilder()
'solutionDrive\MultiStepBundle\Controller\DefaultStepController::renderAction'
)
->end()
->scalarNode('stepRequiredChecker')
->defaultValue('sd.multistep.step_checker.default')
->end()
->end()
->end()
->end()
Expand Down
11 changes: 9 additions & 2 deletions src/DependencyInjection/MultiStepExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;

class MultiStepExtension extends Extension
Expand All @@ -38,8 +39,14 @@ public function load(array $configs, ContainerBuilder $container)
private function parseFlows(array $flowsArray, ContainerBuilder $container): void
{
$registryDefinition = $container->getDefinition('sd.multistep.flow_registry');
foreach ($flowsArray as $id => $config) {
$registryDefinition->addMethodCall('addByConfig', [$id, $config]);
foreach ($flowsArray as $id => $flowConfig) {
$flowConfig['steps'] = array_map(function (array $options): array {
if (isset($options['stepRequiredChecker'])) {
$options['stepRequiredChecker'] = new Reference($options['stepRequiredChecker']);
}
return $options;
}, $flowConfig['steps']);
$registryDefinition->addMethodCall('addByConfig', [$id, $flowConfig]);
}
}
}
1 change: 1 addition & 0 deletions src/Factory/MultiStepFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function createFromConfig(string $id, array $config): MultiStepInterface
$step->setSlug($config['slug']);
$step->setTemplate($config['template']);
$step->setControllerAction($config['controller']);
$step->setStepRequiredChecker($config['stepRequiredChecker']);
return $step;
}
}
15 changes: 15 additions & 0 deletions src/Model/MultiStep.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

namespace solutionDrive\MultiStepBundle\Model;

use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

class MultiStep implements MultiStepInterface
{
/** @var string */
Expand All @@ -26,6 +28,9 @@ class MultiStep implements MultiStepInterface
/** @var string */
private $controllerAction = '';

/** @var StepRequiredCheckerInterface */
private $stepRequiredChecker;

public function getId(): string
{
return $this->id;
Expand Down Expand Up @@ -75,4 +80,14 @@ public function setControllerAction(string $controllerAction): void
{
$this->controllerAction = $controllerAction;
}

public function getStepRequiredChecker(): StepRequiredCheckerInterface
{
return $this->stepRequiredChecker;
}

public function setStepRequiredChecker(StepRequiredCheckerInterface $stepRequiredChecker): void
{
$this->stepRequiredChecker = $stepRequiredChecker;
}
}
6 changes: 6 additions & 0 deletions src/Model/MultiStepInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

namespace solutionDrive\MultiStepBundle\Model;

use solutionDrive\MultiStepBundle\StepChecker\StepRequiredCheckerInterface;

interface MultiStepInterface
{
public function getId(): string;
Expand All @@ -29,4 +31,8 @@ public function setTemplate(string $slug): void;
public function getControllerAction(): string;

public function setControllerAction(string $controllerAction): void;

public function getStepRequiredChecker(): StepRequiredCheckerInterface;

public function setStepRequiredChecker(StepRequiredCheckerInterface $stepRequiredChecker): void;
}
3 changes: 3 additions & 0 deletions src/Resources/config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ services:
- "@argument_resolver"
- "@sd.multistep.flow_context_factory"
- "@sd.multistep.step_router_factory"

sd.multistep.step_checker.default:
class: solutionDrive\MultiStepBundle\StepChecker\DefaultStepRequiredChecker
18 changes: 18 additions & 0 deletions src/StepChecker/DefaultStepRequiredChecker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);

/*
* Created by solutionDrive GmbH
*
* @copyright 2018 solutionDrive GmbH
*/

namespace solutionDrive\MultiStepBundle\StepChecker;

class DefaultStepRequiredChecker implements StepRequiredCheckerInterface
{
public function check(): bool
{
return true;
}
}
15 changes: 15 additions & 0 deletions src/StepChecker/StepRequiredCheckerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);

/*
* Created by solutionDrive GmbH
*
* @copyright 2018 solutionDrive GmbH
*/

namespace solutionDrive\MultiStepBundle\StepChecker;

interface StepRequiredCheckerInterface
{
public function check(): bool;
}

0 comments on commit 93053e6

Please sign in to comment.