RunnerLee /
heshen
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * @author: RunnerLee |
||
| 4 | * @email: [email protected] |
||
| 5 | * @time: 2018-02 |
||
| 6 | */ |
||
| 7 | |||
| 8 | namespace Runner\Heshen; |
||
| 9 | |||
| 10 | use Closure; |
||
| 11 | use Runner\Heshen\Event\Event; |
||
| 12 | use Runner\Heshen\Support\Str; |
||
| 13 | use Runner\Heshen\Support\StateEvents; |
||
| 14 | use Runner\Heshen\Exceptions\LogicException; |
||
| 15 | use Runner\Heshen\Exceptions\StateNotFoundException; |
||
| 16 | use Symfony\Component\EventDispatcher\EventDispatcher; |
||
| 17 | use Runner\Heshen\Exceptions\TransitionNotFoundException; |
||
| 18 | |||
| 19 | class Blueprint |
||
| 20 | { |
||
| 21 | /** |
||
| 22 | * @var State[] |
||
| 23 | */ |
||
| 24 | protected $states = []; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * @var Transition[] |
||
| 28 | */ |
||
| 29 | protected $transitions = []; |
||
| 30 | |||
| 31 | /** |
||
| 32 | * @var EventDispatcher |
||
| 33 | */ |
||
| 34 | protected $dispatcher; |
||
| 35 | |||
| 36 | /** |
||
| 37 | * Blueprint constructor. |
||
| 38 | */ |
||
| 39 | 11 | public function __construct() |
|
| 40 | { |
||
| 41 | 11 | $this->dispatcher = new EventDispatcher(); |
|
| 42 | |||
| 43 | 11 | $this->configure(); |
|
| 44 | 11 | } |
|
| 45 | |||
| 46 | /** |
||
| 47 | * @param $name |
||
| 48 | * |
||
| 49 | * @return Transition |
||
| 50 | */ |
||
| 51 | 6 | public function getTransition(string $name): Transition |
|
| 52 | { |
||
| 53 | 6 | if (array_key_exists($name, $this->transitions)) { |
|
| 54 | 5 | return $this->transitions[$name]; |
|
| 55 | } |
||
| 56 | |||
| 57 | 1 | throw new TransitionNotFoundException($name); |
|
| 58 | } |
||
| 59 | |||
| 60 | /** |
||
| 61 | * @param $name |
||
| 62 | * |
||
| 63 | * @return State |
||
| 64 | */ |
||
| 65 | 10 | public function getState(string $name): State |
|
| 66 | { |
||
| 67 | 10 | if (array_key_exists($name, $this->states)) { |
|
| 68 | 10 | return $this->states[$name]; |
|
| 69 | } |
||
| 70 | |||
| 71 | 1 | throw new StateNotFoundException($name); |
|
| 72 | } |
||
| 73 | |||
| 74 | /** |
||
| 75 | * @return EventDispatcher |
||
| 76 | */ |
||
| 77 | 3 | public function getDispatcher(): EventDispatcher |
|
| 78 | { |
||
| 79 | 3 | return $this->dispatcher; |
|
| 80 | } |
||
| 81 | |||
| 82 | /** |
||
| 83 | * @param string $name |
||
| 84 | * @param string $type |
||
| 85 | * |
||
| 86 | * @return Blueprint |
||
| 87 | */ |
||
| 88 | 10 | protected function addState(string $name, string $type): self |
|
| 89 | { |
||
| 90 | 10 | $this->states[$name] = new State($name, $type); |
|
| 91 | |||
| 92 | 10 | return $this; |
|
| 93 | } |
||
| 94 | |||
| 95 | /** |
||
| 96 | * @param string $name |
||
| 97 | * @param string|array $from |
||
| 98 | * @param string $to |
||
| 99 | * @param null $checker |
||
|
0 ignored issues
–
show
Documentation
Bug
introduced
by
Loading history...
|
|||
| 100 | * |
||
| 101 | * @return $this |
||
| 102 | */ |
||
| 103 | 10 | protected function addTransition(string $name, $from, string $to, $checker = null): self |
|
| 104 | { |
||
| 105 | 10 | $from = (array) $from; |
|
| 106 | 10 | $fromStates = array_map(function ($state) { |
|
| 107 | 10 | return $this->getState($state); |
|
| 108 | 10 | }, $from); |
|
| 109 | 10 | $this->transitions[$name] = new Transition( |
|
| 110 | 10 | $name, |
|
| 111 | 10 | $fromStates, |
|
| 112 | 10 | $this->getState($to), |
|
| 113 | 10 | $checker |
|
| 114 | ); |
||
| 115 | |||
| 116 | 10 | $preMethod = Str::studly("pre{$name}"); |
|
| 117 | 10 | $postMethod = Str::studly("post{$name}"); |
|
| 118 | |||
| 119 | 10 | if (method_exists($this, $preMethod)) { |
|
| 120 | 10 | $this->dispatcher->addListener( |
|
| 121 | 10 | StateEvents::PRE_TRANSITION . $name, |
|
| 122 | 10 | $this->eventListener($preMethod) |
|
| 123 | ); |
||
| 124 | } |
||
| 125 | |||
| 126 | 10 | if (method_exists($this, $postMethod)) { |
|
| 127 | 10 | $this->dispatcher->addListener( |
|
| 128 | 10 | StateEvents::POST_TRANSITION . $name, |
|
| 129 | 10 | $this->eventListener($postMethod) |
|
| 130 | ); |
||
| 131 | } |
||
| 132 | |||
| 133 | 10 | return $this; |
|
| 134 | } |
||
| 135 | |||
| 136 | /** |
||
| 137 | * @param $method |
||
| 138 | * |
||
| 139 | * @return Closure |
||
| 140 | */ |
||
| 141 | protected function eventListener($method): Closure |
||
| 142 | { |
||
| 143 | 10 | return function (Event $event) use ($method) { |
|
| 144 | 1 | return call_user_func([$this, $method], $event->getStateful(), $event->getParameters()); |
|
| 145 | 10 | }; |
|
| 146 | } |
||
| 147 | |||
| 148 | 1 | protected function configure(): void |
|
| 149 | { |
||
| 150 | 1 | throw new LogicException('you must overwrite the configure method in the concrete blueprint class'); |
|
| 151 | } |
||
| 152 | } |
||
| 153 |