CommandBusUndoable::handlerUndo()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 10
rs 10
1
<?php
2
3
namespace Joselfonseca\LaravelTactician;
4
5
use League\Tactician\CommandBus;
6
use League\Tactician\Exception\InvalidCommandException;
7
use League\Tactician\Exception\InvalidMiddlewareException;
8
use League\Tactician\Middleware;
9
10
11
/**
12
 * Receives a command and sends it through a chain of middleware for processing.
13
 *
14
 * @final
15
 */
16
class CommandBusUndoable extends CommandBus // Not really, but L for Liskov in SOLID Principles applies here too
17
{
18
    /**
19
     * @var callable
20
     */
21
    private $middlewareUndoChain;
22
23
    /**
24
     * @var callable
25
     */
26
    private $middlewareRedoChain;
27
28
    /**
29
     * @param Middleware[] $middleware
30
     */
31
    public function __construct(array $middleware)
32
    {
33
        $this->middlewareUndoChain = $this->createExecutionChain($middleware, 'executeUndo');
34
        $this->middlewareRedoChain = $this->createExecutionChain($middleware, 'executeRedo');
35
    }
36
37
    /**
38
     * Executes the given command and optionally returns a value
39
     *
40
     * @param object $command
41
     *
42
     * @return mixed
43
     */
44
    public function handlerUndo($command)
45
    {
46
        if (is_object($command)) {
47
            return $command;
48
        }
49
        if (!is_object($command)) {
50
            throw InvalidCommandException::forUnknownValue($command);
51
        }
52
53
        return ($this->middlewareUndoChain)($command);
54
    }
55
56
    public function handlerRedo($command)
57
    {
58
        if (is_object($command)) {
59
            return $command;
60
        }
61
        if (!is_object($command)) {
62
            throw InvalidCommandException::forUnknownValue($command);
63
        }
64
65
        return ($this->middlewareRedoChain)($command);
66
    }
67
68
    private function createExecutionChain($middlewareList, $executor)
69
    {
70
        $lastCallable = function () {
71
            // the final callable is a no-op
72
        };
73
74
        while ($middleware = array_pop($middlewareList)) {
75
            if (! $middleware instanceof Middleware) {
76
                throw InvalidMiddlewareException::forMiddleware($middleware);
77
            }
78
79
            $lastCallable = function ($command) use ($middleware, $lastCallable, $executor) {
80
                return $middleware->{$executor}($command, $lastCallable);
81
            };
82
        }
83
84
        return $lastCallable;
85
    }
86
}
87