1 | <?php |
||
2 | |||
3 | namespace Joselfonseca\LaravelTactician; |
||
4 | |||
5 | use Joselfonseca\LaravelTactician\Handler\MethodNameInflectorUndoable; |
||
6 | use Joselfonseca\LaravelTactician\Handler\CommandNameExtractorUndoable; |
||
7 | use Joselfonseca\LaravelTactician\Locator\LocatorInterface; |
||
8 | use Joselfonseca\LaravelTactician\Middleware\LockingMiddlewareUndoable; |
||
9 | use Joselfonseca\LaravelTactician\Handler\CommandHandlerMiddlewareUndoable; |
||
10 | use Joselfonseca\LaravelTactician\Exception\CommandHistoryIsEmptyException; |
||
11 | use Joselfonseca\LaravelTactician\Exception\CommandHistoryWasEmptiedException; |
||
12 | use Joselfonseca\LaravelTactician\Exception\RedoCommandHistoryIsEmptyException; |
||
13 | |||
14 | /** |
||
15 | * The default Command bus Using Tactician, this is an implementation to dispatch commands to their handlers |
||
16 | * trough a middleware stack, every class is resolved from the laravel's service container. |
||
17 | * |
||
18 | * @package Joselfonseca\LaravelTactician |
||
19 | */ |
||
20 | class BusUndoable extends Bus implements CommandBusUndoableInterface |
||
21 | { |
||
22 | private $commandHistoryCounter = -1; // history is empty |
||
23 | private $reDoCommandHistoryCounter = -1; // redo history is empty |
||
24 | private $commandHistory = []; |
||
25 | private $reDoCommandHistory = []; |
||
26 | |||
27 | public function __construct( |
||
28 | MethodNameInflectorUndoable $MethodNameInflector, |
||
29 | CommandNameExtractorUndoable $CommandNameExtractor, |
||
30 | LocatorInterface $HandlerLocator |
||
31 | ) { |
||
32 | parent::__construct($MethodNameInflector, $CommandNameExtractor, $HandlerLocator); |
||
33 | |||
34 | // $this->commandHistoryCounter = $this->reDoCommandHistoryCounter = -1; |
||
35 | } |
||
36 | |||
37 | /** |
||
38 | * Dispatch a command and recall it |
||
39 | * |
||
40 | * @param object $command Command to be dispatched |
||
41 | * @param array $input Array of input to map to the command |
||
42 | * @param array $middleware Array of middleware class name to add to the stack, they are resolved from the laravel container |
||
43 | * @return mixed |
||
44 | */ |
||
45 | public function dispatch($command, array $input = [], array $middleware = []) |
||
46 | { |
||
47 | $commandDispatched = parent::dispatch($command, $input, $middleware); |
||
48 | |||
49 | $this->pushCommandHistory( [clone $commandDispatched, $middleware] ); // Memento Pattern |
||
50 | |||
51 | return $commandDispatched; |
||
52 | } |
||
53 | |||
54 | private function pushCommandHistory (array $commandDispatchedAndMiddleware) |
||
55 | { |
||
56 | $this->commandHistory[++$this->commandHistoryCounter] = $commandDispatchedAndMiddleware; |
||
57 | } |
||
58 | |||
59 | public function undo() |
||
60 | { |
||
61 | try{ |
||
62 | $commandDispatchedAndMiddleware = $this->popCommandHistory(); |
||
63 | $this->pushRedoCommandHistory($commandDispatchedAndMiddleware); |
||
64 | |||
65 | $this->handleTheUndoCommand($commandDispatchedAndMiddleware[0], $commandDispatchedAndMiddleware[1]); |
||
66 | |||
67 | return $this->topCommandHistory()[0]; |
||
68 | |||
69 | }catch (CommandHistoryWasEmptiedException $exception){} |
||
0 ignored issues
–
show
Coding Style
Comprehensibility
introduced
by
![]() |
|||
70 | } |
||
71 | |||
72 | private function popCommandHistory() |
||
73 | { |
||
74 | if ($this->commandHistoryCounter == -1) { |
||
75 | throw new CommandHistoryIsEmptyException(); |
||
76 | } |
||
77 | |||
78 | $commandDispatchedAndMiddleware = $this->commandHistory[$this->commandHistoryCounter]; |
||
79 | unset($this->commandHistory[$this->commandHistoryCounter]); |
||
80 | --$this->commandHistoryCounter; |
||
81 | |||
82 | return $commandDispatchedAndMiddleware; |
||
83 | } |
||
84 | |||
85 | private function topCommandHistory() |
||
86 | { |
||
87 | if ($this->commandHistoryCounter == -1){ |
||
88 | throw new CommandHistoryWasEmptiedException(); |
||
89 | } |
||
90 | |||
91 | return $this->commandHistory[$this->commandHistoryCounter]; |
||
92 | } |
||
93 | |||
94 | private function pushRedoCommandHistory(array $commandDispatchedAndMiddleware) |
||
95 | { |
||
96 | $this->reDoCommandHistory[++$this->reDoCommandHistoryCounter] = $commandDispatchedAndMiddleware; |
||
97 | } |
||
98 | |||
99 | private function handleTheUndoCommand($commandDispatched, array $middleware): void |
||
100 | { |
||
101 | $this->bus = new CommandBusUndoable( |
||
102 | array_merge( |
||
103 | [new LockingMiddlewareUndoable()], |
||
104 | $this->resolveMiddleware(array_reverse($middleware)), // in reversed order |
||
105 | [new CommandHandlerMiddlewareUndoable($this->CommandNameExtractor, $this->HandlerLocator, $this->MethodNameInflector)] |
||
106 | ) |
||
107 | ); |
||
108 | $this->bus->handlerUndo($commandDispatched); |
||
109 | } |
||
110 | |||
111 | public function redo() |
||
112 | { |
||
113 | $commandDispatchedAndMiddleware = $this->popRedoCommandHistory(); |
||
114 | $this->pushCommandHistory($commandDispatchedAndMiddleware); |
||
115 | |||
116 | $this->handleTheRedoCommand($commandDispatchedAndMiddleware[0], $commandDispatchedAndMiddleware[1]); |
||
117 | |||
118 | return $commandDispatchedAndMiddleware[0]; |
||
119 | } |
||
120 | |||
121 | private function popRedoCommandHistory() |
||
122 | { |
||
123 | if( $this->reDoCommandHistoryCounter == -1 ) { |
||
124 | throw new RedoCommandHistoryIsEmptyException(); |
||
125 | } |
||
126 | |||
127 | $commandDispatchedAndMiddleware = $this->reDoCommandHistory[$this->reDoCommandHistoryCounter]; |
||
128 | unset($this->reDoCommandHistory[$this->reDoCommandHistoryCounter]); |
||
129 | --$this->reDoCommandHistoryCounter; |
||
130 | |||
131 | return $commandDispatchedAndMiddleware; |
||
132 | } |
||
133 | |||
134 | private function handleTheRedoCommand($commandDispatched, $middleware): void |
||
135 | { |
||
136 | $this->bus = new CommandBusUndoable( |
||
137 | array_merge( |
||
138 | [new LockingMiddlewareUndoable()], |
||
139 | $this->resolveMiddleware($middleware), // in original order again !!!! |
||
140 | [new CommandHandlerMiddlewareUndoable($this->CommandNameExtractor, $this->HandlerLocator, $this->MethodNameInflector)] |
||
141 | ) |
||
142 | ); |
||
143 | $this->bus->handlerRedo($commandDispatched); |
||
144 | } |
||
145 | |||
146 | public function clearHistory() |
||
147 | { |
||
148 | $this->commandHistory = []; |
||
149 | $this->reDoCommandHistory = []; |
||
150 | $this->commandHistoryCounter = $this->reDoCommandHistoryCounter = -1; |
||
151 | } |
||
152 | |||
153 | public function dump() |
||
154 | {return; |
||
155 | echo PHP_EOL.'commandHistoryCounter: '.$this->commandHistoryCounter; |
||
0 ignored issues
–
show
echo Joselfonseca\Larave...->commandHistoryCounter is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
156 | echo PHP_EOL.'reDoCommandHistoryCounter: '.$this->reDoCommandHistoryCounter.PHP_EOL; |
||
157 | } |
||
158 | } |
||
159 |