diff options
Diffstat (limited to 'vendor/gipfl/icinga-cli-daemon/src/StateMachine.php')
-rw-r--r-- | vendor/gipfl/icinga-cli-daemon/src/StateMachine.php | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/vendor/gipfl/icinga-cli-daemon/src/StateMachine.php b/vendor/gipfl/icinga-cli-daemon/src/StateMachine.php new file mode 100644 index 0000000..d8ec470 --- /dev/null +++ b/vendor/gipfl/icinga-cli-daemon/src/StateMachine.php @@ -0,0 +1,113 @@ +<?php + +namespace gipfl\IcingaCliDaemon; + +use RuntimeException; + +trait StateMachine +{ + /** @var string */ + private $currentState; + + /** @var array [fromState][toState] = [callback, ...] */ + private $allowedTransitions = []; + + /** @var array [state] = [callback, ...] */ + private $onState = []; + + public function initializeStateMachine($initialState) + { + if ($this->currentState !== null) { + throw new RuntimeException('StateMachine has already been initialized'); + } + $this->currentState = $initialState; + } + + /** + * @param string|array $fromState + * @param string $toState + * @param callable $callback + * @return $this + */ + public function onTransition($fromState, $toState, $callback) + { + if (is_array($fromState)) { + foreach ($fromState as $state) { + $this->onTransition($state, $toState, $callback); + } + } else { + $this->allowTransition($fromState, $toState); + $this->allowedTransitions[$fromState][$toState][] = $callback; + } + + return $this; + } + + public function allowTransition($fromState, $toState) + { + if (! isset($this->allowedTransitions[$fromState][$toState])) { + $this->allowedTransitions[$fromState][$toState] = []; + } + + return $this; + } + + /** + * @param $state + * @param $callback + * @return $this + */ + public function onState($state, $callback) + { + if (! isset($this->onState[$state])) { + $this->onState[$state] = []; + } + + $this->onState[$state][] = $callback; + + return $this; + } + + public function getState() + { + if ($this->currentState === null) { + throw new RuntimeException('StateMachine has not been initialized'); + } + + return $this->currentState; + } + + public function setState($state) + { + $fromState = $this->getState(); + if ($this->canTransit($fromState, $state)) { + $this->currentState = $state; + $this->runStateTransition($fromState, $state); + } else { + throw new RuntimeException(sprintf( + 'A transition from %s to %s is not allowed', + $fromState, + $state + )); + } + } + + private function runStateTransition($fromState, $toState) + { + if (isset($this->allowedTransitions[$fromState][$toState])) { + foreach ($this->allowedTransitions[$fromState][$toState] as $callback) { + $callback(); + } + } + if (isset($this->onState[$toState])) { + foreach ($this->onState[$toState] as $callback) { + $callback(); + } + } + } + + public function canTransit($fromState, $toState) + { + return isset($this->allowedTransitions[$fromState][$toState]); + } +} |