Completed
Branch FET-10702-command-factory (48c5de)
by
unknown
14:40
created

CommandHandlerManager::getCommandHandler()   C

Complexity

Conditions 7
Paths 15

Size

Total Lines 33
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 21
nc 15
nop 2
dl 0
loc 33
rs 6.7272
c 1
b 0
f 0
1
<?php
2
3
namespace EventEspresso\core\services\commands;
4
5
use DomainException;
6
use EventEspresso\core\services\loaders\LoaderInterface;
7
8
if (! defined('EVENT_ESPRESSO_VERSION')) {
9
    exit('No direct script access allowed');
10
}
11
12
13
14
/**
15
 * Class CommandHandlerManager
16
 * Connects a Command with its corresponding Command Handler
17
 * Command Handlers can be specified explicitly using addCommandHandler()
18
 * or determined dynamically if the Command and Command Handler share the exact same namespace
19
 *
20
 * @package       Event Espresso
21
 * @author        Brent Christensen
22
 * @since         4.9.0
23
 */
24
class CommandHandlerManager implements CommandHandlerManagerInterface
25
{
26
27
    /**
28
     * @var CommandHandlerInterface[] $command_handlers
29
     */
30
    protected $command_handlers;
31
32
    /**
33
     * @type LoaderInterface $loader
34
     */
35
    private $loader;
36
37
38
39
    /**
40
     * CommandHandlerManager constructor
41
     *
42
     * @param LoaderInterface $loader
43
     */
44
    public function __construct(LoaderInterface $loader)
45
    {
46
        $this->loader = $loader;
47
    }
48
49
50
51
    /**
52
     * By default, Commands and CommandHandlers would normally
53
     * reside in the same folder under the same namespace,
54
     * and the names of the two classes would only differ in that
55
     * one ends in "Command" and the other ends in "CommandHandler".
56
     * However, if you wanted to utilize a CommandHandler from somewhere else,
57
     * then this method allows you to add that CommandHandler and specify the FQCN
58
     * (Fully Qualified ClassName) for the Command class that it should be used for.
59
     * For example:
60
     *      by default the "Vendor\some\namespace\DoSomethingCommand"
61
     *      would resolve to using "Vendor\some\namespace\DoSomethingCommandHandler"
62
     *      but if you wanted to instead process that commend using:
63
     *      "Vendor\a\totally\different\namespace\for\DoSomethingCommandHandler"
64
     *      then the following code:
65
     *      $CommandHandlerManager = $this->loader->getShared( 'CommandHandlerManagerInterface' );
66
     *      $CommandHandlerManager->addCommandHandler(
67
     *          new Vendor\a\totally\different\namespace\for\DoSomethingCommandHandler(),
68
     *          'Vendor\some\namespace\DoSomethingCommand'
69
     *      );
70
     *      would result in the alternate CommandHandler being used to process that Command
71
     *
72
     * @param CommandHandlerInterface $command_handler
73
     * @param string                  $fqcn_for_command Fully Qualified ClassName for Command
74
     * @return void
75
     * @throws InvalidCommandHandlerException
76
     */
77
    public function addCommandHandler(CommandHandlerInterface $command_handler, $fqcn_for_command = '')
78
    {
79
        $command = ! empty($fqcn_for_command)
80
            ? $fqcn_for_command
81
            : str_replace('CommandHandler', 'Command', get_class($command_handler));
82
        if (empty($command)) {
83
            throw new InvalidCommandHandlerException($command);
84
        }
85
        $this->command_handlers[$command] = $command_handler;
86
    }
87
88
89
90
    /**
91
     * @param CommandInterface $command
92
     * @param CommandBusInterface       $command_bus
93
     * @return mixed
94
     * @throws DomainException
95
     * @throws CommandHandlerNotFoundException
96
     */
97
    public function getCommandHandler(CommandInterface $command, CommandBusInterface $command_bus = null)
98
    {
99
        $command_name = get_class($command);
100
        $command_handler = apply_filters(
101
            'FHEE__EventEspresso_core_services_commands_CommandHandlerManager__getCommandHandler__command_handler',
102
            str_replace('Command', 'CommandHandler', $command_name),
103
            $command
104
        );
105
        $handler = null;
106
        // has a command handler already been set for this class ?
107
        // if not, can we find one via the FQCN ?
108
        if (isset($this->command_handlers[$command_name])) {
109
            $handler = $this->command_handlers[$command_name];
110
        } else if (class_exists($command_handler)) {
111
            $handler = $this->loader->getShared($command_handler);
112
        }
113
        // if Handler requires an instance of the CommandBus, but that has not yet been set
114
        if ($handler instanceof CompositeCommandHandler && ! $handler->commandBus() instanceof CommandBusInterface) {
115
            if (! $command_bus instanceof CommandBusInterface) {
116
                throw new DomainException(
117
                    esc_html__(
118
                        'CompositeCommandHandler classes require an instance of the CommandBus.',
119
                        'event_espresso'
120
                    )
121
                );
122
            }
123
            $handler->setCommandBus($command_bus);
124
        }
125
        if ($handler instanceof CommandHandlerInterface) {
126
            return $handler;
127
        }
128
        throw new CommandHandlerNotFoundException($command_handler);
129
    }
130
131
132
}
133
// End of file CommandHandlerManager.php
134
// Location: core/services/commands/CommandHandlerManager.php