Created
April 9, 2015 19:10
-
-
Save markkimsal/5333142aab19eff90af1 to your computer and use it in GitHub Desktop.
workflow with callbacks
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 | |
namespace PHPWorkflow; | |
trait EventEmitterTrait { | |
protected $listeners = []; | |
public function on($event, callable $listener) | |
{ | |
if (!isset($this->listeners[$event])) { | |
$this->listeners[$event] = []; | |
} | |
$this->listeners[$event][] = $listener; | |
} | |
public function once($event, callable $listener) | |
{ | |
$onceListener = function () use (&$onceListener, $event, $listener) { | |
$this->removeListener($event, $onceListener); | |
call_user_func_array($listener, func_get_args()); | |
}; | |
$this->on($event, $onceListener); | |
} | |
public function removeListener($event, callable $listener) | |
{ | |
if (isset($this->listeners[$event])) { | |
$index = array_search($listener, $this->listeners[$event], true); | |
if (false !== $index) { | |
unset($this->listeners[$event][$index]); | |
} | |
} | |
} | |
public function removeAllListeners($event = null) | |
{ | |
if ($event !== null) { | |
unset($this->listeners[$event]); | |
} else { | |
$this->listeners = []; | |
} | |
} | |
public function listeners($event) | |
{ | |
return isset($this->listeners[$event]) ? $this->listeners[$event] : []; | |
} | |
public function emit($event, array $arguments = []) | |
{ | |
foreach ($this->listeners($event) as $listener) { | |
call_user_func_array($listener, $arguments); | |
} | |
} | |
}; | |
trait DefaultWorkflow { | |
public $currentState = 0; | |
protected $listTransitions; | |
public function addTransitionFrom($state, $cb) { | |
$this->listTransitions[$state] = $cb; | |
} | |
public function process($input) { | |
$newstate = $this->listTransitions[$this->currentState]($input); | |
if ($newstate == NULL) { | |
return $this; | |
} | |
if ($newstate !== $this->currentState) { | |
$this->emit('statechange', array($this->currentState, $newstate)); | |
$this->emit($newstate); | |
} | |
$this->currentState = $newstate; | |
return $this; | |
} | |
} | |
class DocumentPublish { | |
use DefaultWorkflow; | |
use EventEmitterTrait; | |
public $currentState = ''; | |
public function __construct() { | |
$this->addTransitionFrom('', function($input) { | |
if ($input == 'promote') { | |
return 'draft'; | |
} | |
}); | |
$this->addTransitionFrom('draft', function($input) { | |
if ($input == 'promote') { | |
return 'review'; | |
} | |
}); | |
$this->addTransitionFrom('review', function($input) { | |
if ($input == 'promote') { | |
return 'published'; | |
} | |
if ($input == 'demote') { | |
return 'draft'; | |
} | |
}); | |
$this->addTransitionFrom('published', function($input) { | |
if ($input == 'demote') { | |
return 'review'; | |
} | |
}); | |
} | |
} | |
$wf = new DocumentPublish(); | |
$record = (object)array();// simulate active record pattern | |
$record->status = ''; | |
$wf->on('draft', function() use($record) { | |
$record->status = 'draft'; | |
//$record->save(); | |
}); | |
$wf->on('review', function() use($record) { | |
$record->status = 'review'; | |
//$record->save(); | |
}); | |
$wf->on('published', function() use($record) { | |
$record->status = 'published'; | |
//$record->save(); | |
}); | |
$wf->on('statechange', function($oldstate, $newstate) use($record) { | |
echo "My state changed, it was $oldstate, it's now $newstate.\n"; | |
}); | |
echo 'workflow state: ['.$wf->currentState."]\n"; | |
echo 'record status: ['.$record->status."]\n"; | |
$wf->process('promote'); | |
echo 'workflow state: ['.$wf->currentState."]\n"; | |
echo 'record status: ['.$record->status."]\n"; | |
$wf->process('promote'); | |
echo 'workflow state: ['.$wf->currentState."]\n"; | |
echo 'record status: ['.$record->status."]\n"; | |
$wf->process('promote'); | |
echo 'workflow state: ['.$wf->currentState."]\n"; | |
echo 'record status: ['.$record->status."]\n"; | |
$wf->process('demote'); | |
echo 'workflow state: ['.$wf->currentState."]\n"; | |
echo 'record status: ['.$record->status."]\n"; | |
//output | |
/* | |
workflow state: [] | |
record status: [] | |
My state changed, it was , it's now draft. | |
workflow state: [draft] | |
record status: [draft] | |
My state changed, it was draft, it's now review. | |
workflow state: [review] | |
record status: [review] | |
My state changed, it was review, it's now published. | |
workflow state: [published] | |
record status: [published] | |
My state changed, it was published, it's now review. | |
workflow state: [review] | |
record status: [review] | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment