Created
March 17, 2016 15:00
-
-
Save rskuipers/df208a4cf41040a35d5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ValidationFlow | |
{ | |
/** | |
* @var ValidationStep[] | |
*/ | |
private $steps = []; | |
/** | |
* @var ValidationExit[] | |
*/ | |
private $exits = []; | |
/** | |
* @var string | |
*/ | |
private $initialStep; | |
/** | |
* @param string $stepName | |
*/ | |
public function setInitialStep($stepName) | |
{ | |
$this->initialStep = $stepName; | |
} | |
/** | |
* @param array $steps | |
* @return $this | |
*/ | |
public function registerSteps(array $steps) | |
{ | |
array_walk($steps, [$this, 'registerStep']); | |
return $this; | |
} | |
/** | |
* @param ValidationStep $step | |
* @return $this | |
*/ | |
public function registerStep(ValidationStep $step) | |
{ | |
$stepName = get_class($step); | |
if (count($this->steps) === 0 && $this->initialStep === null) { | |
$this->setInitialStep($stepName); | |
} | |
$step->setFlow($this); | |
$this->steps[$stepName] = $step; | |
return $this; | |
} | |
/** | |
* @param array $exits | |
* @return $this | |
*/ | |
public function registerExits(array $exits) | |
{ | |
array_walk($exits, [$this, 'registerExit']); | |
return $this; | |
} | |
/** | |
* @param ValidationExit $exit | |
* @return $this | |
*/ | |
public function registerExit(ValidationExit $exit) | |
{ | |
$this->exits[get_class($exit)] = $exit; | |
return $this; | |
} | |
/** | |
* @param string $name | |
* @param mixed $payload | |
* @return bool | |
*/ | |
public function continueTo($name, $payload) | |
{ | |
return $this->steps[$name]->execute($payload); | |
} | |
/** | |
* @param string $name | |
* @param mixed $payload | |
* @return mixed | |
*/ | |
public function exitWith($name, $payload) | |
{ | |
return $this->exits[$name]->execute($payload); | |
} | |
/** | |
* @param mixed $payload | |
* @return bool | |
*/ | |
public function validate($payload) | |
{ | |
return $this->steps[$this->initialStep]->execute($payload); | |
} | |
} | |
interface ValidationExit | |
{ | |
/** | |
* @param mixed $payload | |
* @return bool | |
*/ | |
public function execute($payload); | |
} | |
interface ValidationStep | |
{ | |
/** | |
* @param ValidationFlow $flow | |
*/ | |
public function setFlow(ValidationFlow $flow); | |
/** | |
* @param mixed $payload | |
* @return bool | |
*/ | |
public function execute($payload); | |
} | |
abstract class AbstractValidationStep implements ValidationStep | |
{ | |
/** | |
* @var ValidationFlow | |
*/ | |
private $flow; | |
/** | |
* @param ValidationFlow $flow | |
*/ | |
public function setFlow(ValidationFlow $flow) | |
{ | |
$this->flow = $flow; | |
} | |
/** | |
* @param string $name | |
* @param mixed $payload | |
* @return bool | |
*/ | |
protected function continueTo($name, $payload) | |
{ | |
return $this->flow->continueTo($name, $payload); | |
} | |
/** | |
* @param string $name | |
* @param mixed $payload | |
* @return bool | |
*/ | |
protected function exitWith($name, $payload) | |
{ | |
return $this->flow->exitWith($name, $payload); | |
} | |
} | |
class ExitA implements ValidationExit | |
{ | |
public function execute($payload) | |
{ | |
// Do some stuff | |
return false; // fail! | |
} | |
} | |
class ValidationStepA extends AbstractValidationStep | |
{ | |
public function execute($contract) | |
{ | |
if ($contract->a !== true) { | |
return $this->exitWith(ExitA::class, $contract); | |
} | |
if (!true) { | |
return $this->exitWith(ExitA::class, $contract); | |
} | |
return $this->continueTo(ValidationStepB::class, $contract); | |
} | |
} | |
class ValidationStepB extends AbstractValidationStep | |
{ | |
public function execute($contract) | |
{ | |
return true; // done! | |
} | |
} | |
$flow = new ValidationFlow(); | |
$flow | |
->registerSteps([ | |
new ValidationStepA(), | |
new ValidationStepB(), | |
]) | |
->registerExits([ | |
new ExitA(), | |
]) | |
; | |
$contract = new stdClass(); | |
$contract->a = true; | |
if ($flow->validate($contract)) { | |
echo 'Success!'; | |
} else { | |
echo 'Fail!'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment