|
13 | 13 |
|
14 | 14 | namespace Laudis\Neo4j\Bolt;
|
15 | 15 |
|
| 16 | +use function array_filter; |
| 17 | +use function array_map; |
16 | 18 | use function in_array;
|
17 | 19 |
|
18 | 20 | /**
|
19 | 21 | * @see https://7687.org/bolt/bolt-protocol-server-state-specification-4.html#version-43
|
| 22 | + * |
| 23 | + * @psalm-immutable |
20 | 24 | */
|
21 | 25 | final class ServerStateRepository
|
22 | 26 | {
|
23 |
| - private const KEYS = ['State' => 0, 'Request Message' => 1, 'Triggers Signal' => 2, 'Server Response' => 3, 'New State' => 4]; |
24 |
| - public function canSendMessage(string $state, string $message): bool |
25 |
| - { |
26 |
| - return in_array($message, $this->getMessagesForState($state), true); |
27 |
| - } |
28 |
| - |
29 |
| - public function isValidState(string $state): bool |
30 |
| - { |
31 |
| - return in_array($state, $this->getStates(), true); |
32 |
| - } |
33 |
| - |
34 | 27 | private const TRANSITIONS = [
|
35 | 28 | ['CONNECTED', 'HELLO', null, 'SUCCESS', 'READY'],
|
36 | 29 | ['CONNECTED', 'HELLO', null, 'FAILURE', 'DEFUNCT'],
|
@@ -89,27 +82,95 @@ public function isValidState(string $state): bool
|
89 | 82 | ['INTERRUPTED', 'GOODBYE', 'DISCONNECT', null, 'DEFUNCT'],
|
90 | 83 | ];
|
91 | 84 |
|
| 85 | + /** @var list<StateTransition> */ |
| 86 | + private array $transitions; |
| 87 | + |
| 88 | + public function __construct() |
| 89 | + { |
| 90 | + $this->transitions = array_map(static fn ($x) => StateTransition::fromArray($x), self::TRANSITIONS); |
| 91 | + } |
| 92 | + |
92 | 93 | /**
|
93 |
| - * @return list<string> |
| 94 | + * @return array<string, string|null> |
94 | 95 | */
|
95 |
| - public function getMessagesForState(string $state): array |
| 96 | + public function expectedStates(string $state, string $message): array |
| 97 | + { |
| 98 | + $tbr = []; |
| 99 | + foreach ($this->getAvailableTransitionsForState($state) as $transition) { |
| 100 | + $tbr[$transition->getServerResponse() ?? ''] = $transition->getNewState(); |
| 101 | + } |
| 102 | + |
| 103 | + return $tbr; |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * Returns the expected state for the response. |
| 108 | + */ |
| 109 | + public function expectedStateForResponse(string $state, string $message, string $response): ?string |
| 110 | + { |
| 111 | + return $this->expectedStates($state, $message)[$response] ?? null; |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * Returns the signal if the state transition response triggers one, null otherwise. |
| 116 | + */ |
| 117 | + public function expectedSignalForResponse(string $state, string $message, string $response): ?string |
96 | 118 | {
|
97 |
| - $messages = []; |
98 |
| - foreach (self::TRANSITIONS as $transition) { |
99 |
| - if ($transition[self::KEYS['State']] === $state) { |
100 |
| - $messages[] = $transition[self::KEYS['Request Message']]; |
| 119 | + foreach ($this->getAvailableTransitionsForStateAndMessage($state, $message) as $transition) { |
| 120 | + if ($transition->getTriggersSignal()) { |
| 121 | + return $transition->getTriggersSignal(); |
101 | 122 | }
|
102 | 123 | }
|
103 | 124 |
|
104 |
| - return $messages; |
| 125 | + return null; |
| 126 | + } |
| 127 | + |
| 128 | + /** |
| 129 | + * @return list<StateTransition> |
| 130 | + */ |
| 131 | + public function getAvailableTransitionsForStateAndMessage(string $state, string $message): array |
| 132 | + { |
| 133 | + return array_values(array_filter( |
| 134 | + $this->getAvailableTransitionsForState($state), |
| 135 | + static fn ($x) => $x->getMessage() === $message |
| 136 | + )); |
| 137 | + } |
| 138 | + |
| 139 | + /** |
| 140 | + * Returns the available transitions for the state. |
| 141 | + * |
| 142 | + * @return list<StateTransition> |
| 143 | + */ |
| 144 | + private function getAvailableTransitionsForState(string $state): array |
| 145 | + { |
| 146 | + return array_values( |
| 147 | + array_filter($this->transitions, static fn ($x) => $x->getOriginalState() === $state) |
| 148 | + ); |
| 149 | + } |
| 150 | + |
| 151 | + public function canSendMessage(string $state, string $message): bool |
| 152 | + { |
| 153 | + return in_array($message, $this->getMessagesForState($state), true); |
| 154 | + } |
| 155 | + |
| 156 | + public function isValidState(string $state): bool |
| 157 | + { |
| 158 | + return in_array($state, $this->getStates(), true); |
| 159 | + } |
| 160 | + |
| 161 | + /** |
| 162 | + * @return list<string> |
| 163 | + */ |
| 164 | + public function getMessagesForState(string $state): array |
| 165 | + { |
| 166 | + return array_map(static fn ($x) => $x->getMessage(), $this->getAvailableTransitionsForState($state)); |
105 | 167 | }
|
106 | 168 |
|
107 | 169 | /**
|
108 | 170 | * @return list<string>
|
109 | 171 | */
|
110 | 172 | public function getStates(): array
|
111 | 173 | {
|
112 |
| - /** @var list<string> */ |
113 |
| - return array_unique(array_map(static fn (array $x) => $x[self::KEYS['State']], self::TRANSITIONS)); |
| 174 | + return array_values(array_unique(array_map(static fn ($x) => $x->getOriginalState(), $this->transitions))); |
114 | 175 | }
|
115 | 176 | }
|
0 commit comments