Last active
December 31, 2015 23:09
-
-
Save dadamssg/8057913 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 | |
$obj = new \stdClass; | |
$obj->x = ''; | |
$first = function() use ($obj) { | |
$obj->x .= ' 1 '; | |
yield ControlFlow::NEXT; | |
$obj->x .= ' 2 '; | |
}; | |
$second = function() use ($obj){ | |
$obj->x .= ' 3 '; | |
yield ControlFlow::NEXT; | |
$obj->x .= ' 4 '; | |
}; | |
$third = function() use ($obj){ | |
$obj->x .= ' 5 '; | |
$obj->x .= ' 6 '; | |
return ControlFlow::NEXT; | |
}; | |
$fourth = function() use ($obj){ | |
$obj->x .= ' 7 '; | |
$obj->x .= ' 8 '; | |
return ControlFlow::NEXT; | |
}; | |
$flow = new ControlFlow; | |
$flow->queue($first()) | |
->queue($second()) | |
->queue($third) | |
->queue($fourth); | |
$flow->run(); | |
class ControlFlow | |
{ | |
const NEXT = 'NEXT'; | |
/** | |
* @var array | |
*/ | |
protected $queued = []; | |
/** | |
* @var array | |
*/ | |
protected $initiated = []; | |
/** | |
* Add to the ControlFlow | |
* | |
* @param \Closure|\Generator $item | |
* @return $this | |
* @throws \InvalidArgumentException | |
*/ | |
public function queue($item) | |
{ | |
if ( ! $item instanceof \Closure && ! $item instanceof \Generator) { | |
throw new \InvalidArgumentException('Queued item must be a \Closure or \Generator'); | |
} | |
$this->queued[] = $item; | |
return $this; | |
} | |
/** | |
* Run all queued | |
* | |
* @return void | |
*/ | |
public function run() | |
{ | |
foreach ($this->queued as $queued) { | |
$this->runQueued($queued); | |
} | |
$this->reset(); | |
} | |
/** | |
* Run a queued \Closure or \Generator | |
* | |
* @param \Closure|\Generator $queued | |
* @return void | |
*/ | |
private function runQueued($queued) | |
{ | |
if (in_array($queued, $this->initiated, true)) return; | |
if ($queued instanceof \Generator) { | |
$this->runGenerator($queued); | |
} elseif ($queued instanceof \Closure) { | |
$this->runClosure($queued); | |
} | |
} | |
/** | |
* Run a queued closure | |
* | |
* @param \Closure $closure | |
* @return void | |
*/ | |
private function runClosure(\Closure $closure) | |
{ | |
$this->initiated[] = $closure; | |
if ($closure() === self::NEXT) { | |
$this->initiateNext(); | |
} | |
} | |
/** | |
* Run a queued Generator | |
* | |
* @param \Generator $generator | |
* @return void | |
*/ | |
private function runGenerator(\Generator $generator) | |
{ | |
$this->initiated[] = $generator; | |
foreach ($generator as $result) { | |
if ($result === self::NEXT) { | |
$this->initiateNext(); | |
} | |
} | |
} | |
/** | |
* Initiate the next queued | |
* | |
* @return void | |
*/ | |
private function initiateNext() | |
{ | |
$next = current($this->queued); | |
next($this->queued); | |
$this->runQueued($next); | |
} | |
/** | |
* Reset to run again | |
* | |
* @return void | |
*/ | |
public function reset() | |
{ | |
reset($this->queued); | |
$this->initiated = []; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment