-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
StateMachine.php
92 lines (83 loc) · 2.76 KB
/
StateMachine.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
<?php
namespace sssm;
final class StateMachine
{
public function __construct(private ?State $startState, State ...$states)
{
$this->states = $states;
$this->states[] = $startState;
$this->currentState = $this->startState;
foreach ($this->startState->onStateEnter as $callback) {
$callback($this->startState);
}
}
private ?State $currentState = null;
/**
* @var State[] An array of all states that are registered in the state machine.
*/
private array $states = [];
/**
* @return State[] Returns an array of all states that are registered in the state machine.
*/
public function getRegisteredStates(): array {
return $this->states;
}
/**
* @return State
*/
public function getCurrentState(): State {
return $this->currentState;
}
/**
* @return string
*/
public function getCurrentStateName(): string {
return $this->currentState->getStateName();
}
/**
* @param State $newState
* @return bool true if state changing succeeded.
* @throws StateTransitionNotAllowedException
* @throws StateNotRegisteredInStateMachineException
*/
public function switchState(State $newState):bool{
if(!in_array($newState, $this->states, true)){
throw new StateNotRegisteredInStateMachineException($this->currentState, $newState);
}
if(!in_array($newState, $this->currentState->getAllowedStateTransitions(), true)){
throw new StateTransitionNotAllowedException($this->currentState, $newState);
}
foreach ($this->currentState->onStateLeave as $callback) {
$callback($this->currentState);
}
if($this->currentState = $newState){
foreach ($this->currentState->onLoop as $callback) {
$callback($this->currentState);
}
}
$this->currentState = $newState;
foreach ($this->currentState->onStateEnter as $callback) {
$callback($this->currentState);
}
return true;
}
/**
* @return void Starts the state from the beginning.
* @throws LoopNotAllowedException
*/
public function loop(): void {
if($this->currentState->getCanLoop()) {
foreach ($this->currentState->onStateLeave as $callback) {
$callback($this->currentState);
}
foreach ($this->currentState->onLoop as $callback) {
$callback($this->currentState);
}
foreach ($this->currentState->onStateEnter as $callback) {
$callback($this->currentState);
}
}else{
throw new LoopNotAllowedException($this->currentState);
}
}
}