Skip to content

Instantly share code, notes, and snippets.

@jjsaunier
Created January 9, 2017 15:32
Show Gist options
  • Save jjsaunier/e82f562097973f6f9662cc9e50012833 to your computer and use it in GitHub Desktop.
Save jjsaunier/e82f562097973f6f9662cc9e50012833 to your computer and use it in GitHub Desktop.
<?php
$strategist = new Strategist();
$strategist->respect(function () use ($var) {
return true === $var;
})->then(function () use ($whatever) {
return $whatever->getTrue();
});
$strategist->respect(function () use ($var) {
return false === $var;
})->then(function () use ($whatever) {
return $whatever->getFalse();
});
$strategist->otherwise(function () use ($whatever) {
return $whatever->default();
});
$result = $strategist->resolve(); // depend of matched strategy
<?php
declare(strict_types=1);
namespace Strategy;
class Strategist
{
/**
* @var Strategy[]
*/
private $strategies;
/**
* @var callable
*/
private $otherwise;
public function __construct()
{
$this->strategies = [];
}
/**
* @param $spec
*
* @return Strategy
*/
public function respect($spec) : Strategy
{
$strategy = new Strategy($spec);
$this->strategies[] = $strategy;
return $strategy;
}
/**
* @param callable $callable
*
* @return Strategist
*/
public function otherwise(callable $callable) : self
{
$this->otherwise = $callable;
return $this;
}
/**
* @return mixed
*/
public function resolve()
{
$result = null;
$otherwise = $this->otherwise;
foreach ($this->strategies as $strategy) {
if (false === $strategy->isStatisfied()) {
continue;
}
$result = null;
$stack = $strategy->getHandlerStack();
$stack->rewind();
while ($stack->valid()) {
$handler = $stack->current();
try {
$result = $handler($result);
} catch (\Throwable $e) {
return $otherwise($e);
}
$stack->next();
}
$this->strategies = [];
return $result;
}
return $otherwise();
}
}
<?php
declare(strict_types=1);
namespace Strategy;
class Strategy
{
/**
* @var callable
*/
private $spec;
/**
* @var callable[]
*/
private $handlerStack;
/**
* Strategy constructor.
*
* @param callable $spec
*/
public function __construct(callable $spec)
{
$this->spec = $spec;
$this->handlerStack = new \SplStack();
}
/**
* @return bool
*/
public function isStatisfied() : bool
{
return ($this->spec)();
}
/**
* @param callable $callable
*
* @return Strategy
*/
public function then(callable $callable) : self
{
$this->handlerStack->push($callable);
return $this;
}
/**
* @return \SplStack
*/
public function getHandlerStack() : \SplStack
{
return $this->handlerStack;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment