Completed
Branch FET-9795-new-interfaces (ea072c)
by
unknown
19:19
created

CommandBus   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 73
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 73
rs 10
wmc 7
lcom 1
cbo 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A getCommandHandlerManager() 0 4 1
B execute() 0 23 4
1
<?php
2
namespace EventEspresso\core\services\commands;
3
4
use EventEspresso\core\exceptions\InvalidDataTypeException;
5
use EventEspresso\core\services\commands\middleware\CommandBusMiddlewareInterface;
6
use EventEspresso\core\services\commands\middleware\InvalidCommandBusMiddlewareException;
7
8
if ( ! defined('EVENT_ESPRESSO_VERSION')) {
9
    exit('No direct script access allowed');
10
}
11
12
13
14
/**
15
 * Class CommandBus
16
 * Routes Command objects to their respective CommandHandlers,
17
 * which can then utilize services within the core domain to complete the requested command.
18
 * Normally the CommandBus would be injected into the constructors of classes using it's interface
19
 *      public function __construct( CommandBusInterface $command_bus )
20
 * and then used something like this:
21
 *      $result = $this->command_bus->execute(
22
 *          new Vendor\some\namespace\to\MyCommand(
23
 *              new SomeEntity( $_GET['data_from_HTTP_request'] )
24
 *          )
25
 *      );
26
 * the benefit of using the CommandBus is that it allows other request types,
27
 * such as the API, or CLI, to route data to the same services,
28
 * with less duplication within the client code:
29
 *      $result = $this->command_bus->execute(
30
 *          new Vendor\some\namespace\to\MyCommand(
31
 *              new SomeEntity( $data_from_API_request )
32
 *          )
33
 *      );
34
 * Event Espresso CommandBus Commands, however, are self executing,
35
 * meaning they are capable of routing themselves to the CommandBus,
36
 * because they possess their own internal reference to it.
37
 * So as long as your client code has a reference to the EE_Registry,
38
 * it can use the create() method to generate the required Command objects,
39
 * which will automatically handle resolving their dependency on the CommandBus.
40
 * This means you can simply do the following in your client code:
41
 *      $result = $this->registry
42
 *          ->create(
43
 *              'Vendor\some\namespace\to\MyCommand',
44
 *              array( $request_data )
45
 *          )
46
 *          ->execute();
47
 * without having to inject the CommandBus,
48
 * because you will likely have a reference to EE_Registry
49
 * (or DI container) in your client code already
50
 *
51
 * @package       Event Espresso
52
 * @author        Brent Christensen
53
 * @since         4.9.0
54
 */
55
class CommandBus implements CommandBusInterface
56
{
57
58
    /**
59
     * @type CommandHandlerManagerInterface $command_handler_manager
60
     */
61
    private $command_handler_manager;
62
63
    /**
64
     * @type CommandBusMiddlewareInterface[] $command_bus_middleware
65
     */
66
    private $command_bus_middleware;
67
68
69
70
    /**
71
     * CommandBus constructor
72
     *
73
     * @param CommandHandlerManagerInterface  $command_handler_manager
74
     * @param CommandBusMiddlewareInterface[] $command_bus_middleware
75
     */
76
    public function __construct(
77
        CommandHandlerManagerInterface $command_handler_manager,
78
        $command_bus_middleware = array()
79
    ) {
80
        $this->command_handler_manager = $command_handler_manager;
81
        $this->command_bus_middleware = is_array($command_bus_middleware)
82
            ? $command_bus_middleware
83
            : array($command_bus_middleware);
84
    }
85
86
87
88
    /**
89
     * @return CommandHandlerManagerInterface
90
     */
91
    public function getCommandHandlerManager()
92
    {
93
        return $this->command_handler_manager;
94
    }
95
96
97
98
    /**
99
     * @param \EventEspresso\core\services\commands\CommandInterface $command
100
     * @return mixed
101
     */
102
    public function execute($command)
103
    {
104
        if ( ! $command instanceof CommandInterface) {
105
            throw new InvalidDataTypeException(__METHOD__ . '( $command )', $command, 'CommandInterface');
106
        }
107
        // expose the command to any CommandBus middleware classes
108
        // so that they can execute their logic on the command
109
        $middleware = function ($command) {
0 ignored issues
show
Unused Code introduced by
The parameter $command is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
110
            // do nothing, just need an empty shell to pass along as the last middleware
111
        };
112
        while ($command_bus_middleware = array_pop($this->command_bus_middleware)) {
113
            if ( ! $command_bus_middleware instanceof CommandBusMiddlewareInterface) {
114
                throw new InvalidCommandBusMiddlewareException($command_bus_middleware);
115
            }
116
            $middleware = function ($command) use ($command_bus_middleware, $middleware) {
117
                return $command_bus_middleware->handle($command, $middleware);
118
            };
119
            $middleware($command, $middleware);
120
        }
121
        return $this->command_handler_manager
122
            ->getCommandHandler($command)
123
            ->handle($command);
124
    }
125
126
127
}
128
// End of file CommandBus.php
129
// Location: core/services/commands/CommandBus.php