jagarsoft /
laravel-tactician
| 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
Loading history...
|
|||
| 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 |