DelegatingHandler::selectHandler()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 15
ccs 8
cts 8
cp 1
rs 9.4285
cc 3
eloc 8
nc 3
nop 1
crap 3
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)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

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.

Loading history...
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.
0 ignored issues
show
Documentation introduced by
Should the return type not be integer[]?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
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