1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
* This file is part of the webmozart/console package. |
5
|
|
|
* |
6
|
|
|
* (c) Bernhard Schussek <[email protected]> |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please view the LICENSE |
9
|
|
|
* file that was distributed with this source code. |
10
|
|
|
*/ |
11
|
|
|
|
12
|
|
|
namespace Webmozart\Console\Handler; |
13
|
|
|
|
14
|
|
|
use InvalidArgumentException; |
15
|
|
|
use LogicException; |
16
|
|
|
use Webmozart\Assert\Assert; |
17
|
|
|
use Webmozart\Console\Api\Args\Args; |
18
|
|
|
use Webmozart\Console\Api\Command\Command; |
19
|
|
|
use Webmozart\Console\Api\IO\IO; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Delegates command handling to one of a list of registered handlers. |
23
|
|
|
* |
24
|
|
|
* You can register handlers or factory callbacks that create those handlers |
25
|
|
|
* with the {@link register()} method: |
26
|
|
|
* |
27
|
|
|
* ```php |
28
|
|
|
* $handler = new DelegatingHandler(); |
29
|
|
|
* $handler->register('json', new JsonHandler()); |
30
|
|
|
* $handler->register('xml', function () { |
31
|
|
|
* $handler = new XmlHandler(); |
32
|
|
|
* // ... |
33
|
|
|
* |
34
|
|
|
* return $handler; |
35
|
|
|
* }); |
36
|
|
|
* ``` |
37
|
|
|
* |
38
|
|
|
* The executed handler can be selected with {@link selectHandler()}. You need |
39
|
|
|
* to pass the name of the handler or a callback that receives the command, |
40
|
|
|
* the console arguments and the I/O as parameters: |
41
|
|
|
* |
42
|
|
|
* ```php |
43
|
|
|
* $handler->selectHandler(function (Command $command, Args $args, IO $io) { |
44
|
|
|
* return $args->getOption('format'); |
45
|
|
|
* }); |
46
|
|
|
* ``` |
47
|
|
|
* |
48
|
|
|
* Run {@link handle()} to execute the selected handler: |
49
|
|
|
* |
50
|
|
|
* ```php |
51
|
|
|
* $handler->handle($command, $args, $io); |
52
|
|
|
* ``` |
53
|
|
|
* |
54
|
|
|
* @since 1.0 |
55
|
|
|
* |
56
|
|
|
* @author Bernhard Schussek <[email protected]> |
57
|
|
|
*/ |
58
|
|
|
class DelegatingHandler |
59
|
|
|
{ |
60
|
|
|
/** |
61
|
|
|
* @var object[]|callable[] |
62
|
|
|
*/ |
63
|
|
|
private $handlers = array(); |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* @var string|callable |
67
|
|
|
*/ |
68
|
|
|
private $selectedHandler; |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* {@inheritdoc} |
72
|
|
|
*/ |
73
|
59 |
|
public function handle(Args $args, IO $io, Command $command) |
|
|
|
|
74
|
|
|
{ |
75
|
59 |
|
$handlerName = $this->selectedHandler; |
76
|
|
|
|
77
|
59 |
|
if (!$handlerName) { |
78
|
1 |
|
throw new LogicException('No handler was selected.'); |
79
|
|
|
} |
80
|
|
|
|
81
|
58 |
|
if (is_callable($handlerName)) { |
82
|
54 |
|
$handlerName = call_user_func($handlerName, $args, $io, $command); |
83
|
|
|
} |
84
|
|
|
|
85
|
58 |
|
if (!isset($this->handlers[$handlerName])) { |
86
|
1 |
|
throw new LogicException(sprintf( |
87
|
1 |
|
'The handler "%s" does not exist.', |
88
|
|
|
$handlerName |
89
|
|
|
)); |
90
|
|
|
} |
91
|
|
|
|
92
|
57 |
|
$handler = $this->handlers[$handlerName]; |
93
|
|
|
|
94
|
57 |
|
if (is_callable($handler)) { |
95
|
53 |
|
$handler = call_user_func($handler, $args, $io, $command); |
96
|
|
|
} |
97
|
|
|
|
98
|
57 |
|
return $handler->handle($args, $io, $command); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
/** |
102
|
|
|
* Registers a command handler for the given name. |
103
|
|
|
* |
104
|
|
|
* @param string $name The handler name. |
105
|
|
|
* @param object|callable $handler The handler or a factory callback that |
106
|
|
|
* creates the handler. |
107
|
|
|
*/ |
108
|
63 |
|
public function register($name, $handler) |
109
|
|
|
{ |
110
|
63 |
|
Assert::string($name, 'The handler name must be a string. Got: %s'); |
111
|
61 |
|
Assert::notEmpty($name, 'The handler name must not be empty.'); |
112
|
|
|
|
113
|
60 |
|
if (!is_object($handler)) { |
114
|
53 |
|
Assert::isCallable($handler, 'The handler must be a callable or an object. Got: %s'); |
115
|
|
|
} |
116
|
|
|
|
117
|
59 |
|
$this->handlers[$name] = $handler; |
118
|
|
|
|
119
|
59 |
|
if (!$this->selectedHandler) { |
120
|
59 |
|
$this->selectedHandler = $name; |
121
|
|
|
} |
122
|
59 |
|
} |
123
|
|
|
|
124
|
|
|
/** |
125
|
|
|
* Unregisters the command handler for the given name. |
126
|
|
|
* |
127
|
|
|
* @param string $name The handler name. |
128
|
|
|
*/ |
129
|
2 |
|
public function unregister($name) |
130
|
|
|
{ |
131
|
2 |
|
unset($this->handlers[$name]); |
132
|
|
|
|
133
|
2 |
|
if ($name === $this->selectedHandler) { |
134
|
1 |
|
reset($this->handlers); |
135
|
1 |
|
$this->selectedHandler = key($this->handlers); |
136
|
|
|
} |
137
|
2 |
|
} |
138
|
|
|
|
139
|
|
|
/** |
140
|
|
|
* Returns all registered handler names. |
141
|
|
|
* |
142
|
|
|
* @return string[] The handler names. |
|
|
|
|
143
|
|
|
*/ |
144
|
47 |
|
public function getRegisteredNames() |
145
|
|
|
{ |
146
|
47 |
|
return array_keys($this->handlers); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
/** |
150
|
|
|
* Selects the executed handler. |
151
|
|
|
* |
152
|
|
|
* @param string|callback $handler The name of the handler or a callback |
153
|
|
|
* that returns the name. The callback |
154
|
|
|
* receives the executed {@link Command}, |
155
|
|
|
* the {@link Args} and the {@link IO} as |
156
|
|
|
* arguments. |
157
|
|
|
*/ |
158
|
61 |
|
public function selectHandler($handler) |
159
|
|
|
{ |
160
|
61 |
|
if (!is_callable($handler)) { |
161
|
7 |
|
Assert::string($handler, 'The selected handler must be a callable or a string. Got: %s'); |
162
|
|
|
|
163
|
5 |
|
if (!isset($this->handlers[$handler])) { |
164
|
2 |
|
throw new InvalidArgumentException(sprintf( |
165
|
2 |
|
'The handler "%s" does not exist.', |
166
|
|
|
$handler |
167
|
|
|
)); |
168
|
|
|
} |
169
|
|
|
} |
170
|
|
|
|
171
|
57 |
|
$this->selectedHandler = $handler; |
172
|
57 |
|
} |
173
|
|
|
} |
174
|
|
|
|
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@return
annotation as described here.