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; |
||
156 | echo PHP_EOL.'reDoCommandHistoryCounter: '.$this->reDoCommandHistoryCounter.PHP_EOL; |
||
157 | } |
||
158 | } |
||
159 |