yvoyer /
php-state
| 1 | <?php declare(strict_types=1); |
||
| 2 | /** |
||
| 3 | * This file is part of the php-state project. |
||
| 4 | * |
||
| 5 | * (c) Yannick Voyer <[email protected]> (http://github.com/yvoyer) |
||
| 6 | */ |
||
| 7 | |||
| 8 | namespace Star\Component\State; |
||
| 9 | |||
| 10 | use Star\Component\State\Transitions\ReadOnlyTransition; |
||
| 11 | |||
| 12 | final class TransitionRegistry implements StateRegistry |
||
| 13 | { |
||
| 14 | /** |
||
| 15 | * @var array[] Collection of states indexed by transition name |
||
| 16 | */ |
||
| 17 | private $transitions = []; |
||
| 18 | |||
| 19 | /** |
||
| 20 | * @var array[] Collection of attributes indexed by state name |
||
| 21 | */ |
||
| 22 | private $states = []; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * @param StateTransition $transition |
||
| 26 | */ |
||
| 27 | 47 | public function addTransition(StateTransition $transition): void |
|
| 28 | { |
||
| 29 | 47 | $name = $transition->getName(); |
|
| 30 | 47 | if (isset($this->transitions[$name])) { |
|
| 31 | 1 | throw DuplicateEntryException::duplicateTransition($name); |
|
| 32 | } |
||
| 33 | |||
| 34 | 47 | $transition->onRegister($this); |
|
| 35 | 47 | } |
|
| 36 | |||
| 37 | /** |
||
| 38 | * @param string $name The transition name |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 39 | * |
||
| 40 | * @return StateTransition |
||
| 41 | * @throws NotFoundException |
||
|
0 ignored issues
–
show
|
|||
| 42 | */ |
||
| 43 | 32 | public function getTransition(string $name): StateTransition |
|
| 44 | { |
||
| 45 | 32 | $transition = null; |
|
| 46 | 32 | if (isset($this->transitions[$name]['to'])) { |
|
| 47 | 30 | $transition = new ReadOnlyTransition($this->transitions[$name]['to']); |
|
| 48 | } |
||
| 49 | |||
| 50 | 32 | if (! $transition) { |
|
| 51 | 2 | throw NotFoundException::transitionNotFound($name); |
|
| 52 | } |
||
| 53 | |||
| 54 | 30 | return $transition; |
|
| 55 | } |
||
| 56 | |||
| 57 | 35 | public function addAttribute(string $state, string $attribute): void |
|
| 58 | { |
||
| 59 | 35 | $attributes = [$attribute]; |
|
| 60 | 35 | if ($this->hasState($state)) { |
|
| 61 | 35 | $attributes = \array_merge($this->states[$state], $attributes); |
|
| 62 | } |
||
| 63 | |||
| 64 | 35 | $this->states[$state] = \array_unique($attributes); |
|
| 65 | 35 | } |
|
| 66 | |||
| 67 | /** |
||
| 68 | * @param string $state |
||
| 69 | * @param string[] $attributes |
||
| 70 | */ |
||
| 71 | 52 | private function addAttributes(string $state, array $attributes): void |
|
| 72 | { |
||
| 73 | 52 | \array_map( |
|
| 74 | function ($attribute) use ($state) { |
||
| 75 | 3 | $this->addAttribute($state, $attribute); |
|
| 76 | 52 | }, |
|
| 77 | 52 | $attributes |
|
| 78 | ); |
||
| 79 | 52 | } |
|
| 80 | |||
| 81 | 30 | public function transitionStartsFrom(string $transition, string $state): bool |
|
| 82 | { |
||
| 83 | 30 | $from = []; |
|
| 84 | 30 | if (isset($this->transitions[$transition]['from'])) { |
|
| 85 | 30 | $from = $this->transitions[$transition]['from']; |
|
| 86 | } |
||
| 87 | |||
| 88 | 30 | return \in_array($state, $from, true); |
|
| 89 | } |
||
| 90 | |||
| 91 | 10 | public function hasAttribute(string $state, string $attribute): bool |
|
| 92 | { |
||
| 93 | 10 | if (! $this->hasState($state)) { |
|
| 94 | return false; |
||
| 95 | } |
||
| 96 | |||
| 97 | 10 | return \in_array($attribute, $this->states[$state]); |
|
| 98 | } |
||
| 99 | |||
| 100 | 54 | public function hasState(string $name): bool |
|
| 101 | { |
||
| 102 | 54 | return \array_key_exists($name, $this->states); |
|
| 103 | } |
||
| 104 | |||
| 105 | 3 | public function acceptTransitionVisitor(TransitionVisitor $visitor): void |
|
| 106 | { |
||
| 107 | 3 | foreach ($this->transitions as $transition => $states) { |
|
| 108 | 3 | $visitor->visitTransition($transition); |
|
| 109 | |||
| 110 | 3 | foreach ($states['from'] as $from) { |
|
| 111 | 3 | $visitor->visitFromState($from, $this->states[$from]); |
|
| 112 | } |
||
| 113 | 3 | $visitor->visitToState($states['to'], $this->states[$states['to']]); |
|
| 114 | } |
||
| 115 | 3 | } |
|
| 116 | |||
| 117 | 2 | public function acceptStateVisitor(StateVisitor $visitor): void |
|
| 118 | { |
||
| 119 | 2 | foreach ($this->states as $state => $attributes) { |
|
| 120 | 2 | $visitor->visitState($state, $attributes); |
|
| 121 | } |
||
| 122 | 2 | } |
|
| 123 | |||
| 124 | /** |
||
| 125 | * @param string $transition |
||
| 126 | * @param string $stateName |
||
| 127 | * @param string[] $attributes |
||
| 128 | */ |
||
| 129 | 52 | public function registerStartingState(string $transition, string $stateName, array $attributes = []): void |
|
| 130 | { |
||
| 131 | 52 | $this->initState($stateName); |
|
| 132 | 52 | $this->addAttributes($stateName, $attributes); |
|
| 133 | 52 | $this->transitions[$transition]['from'][] = $stateName; |
|
| 134 | 52 | } |
|
| 135 | |||
| 136 | /** |
||
| 137 | * @param string $transition |
||
| 138 | * @param string $stateName |
||
| 139 | * @param string[] $attributes |
||
| 140 | */ |
||
| 141 | 48 | public function registerDestinationState(string $transition, string $stateName, array $attributes = []): void |
|
| 142 | { |
||
| 143 | 48 | $this->initState($stateName); |
|
| 144 | 48 | $this->addAttributes($stateName, $attributes); |
|
| 145 | 48 | $this->transitions[$transition]['to'] = $stateName; |
|
| 146 | 48 | } |
|
| 147 | |||
| 148 | /** |
||
| 149 | * @param string $state |
||
| 150 | */ |
||
| 151 | 52 | private function initState(string $state): void |
|
| 152 | { |
||
| 153 | 52 | if (!$this->hasState($state)) { |
|
| 154 | 52 | $this->states[$state] = []; |
|
| 155 | } |
||
| 156 | 52 | } |
|
| 157 | } |
||
| 158 |