Passed
Push — master ( 151619...8ae005 )
by PHPinnacle
03:00
created

Dispatcher::dispatch()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 2
nop 2
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 2
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of PHPinnacle/Ensign.
4
 *
5
 * (c) PHPinnacle Team <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
declare(strict_types = 1);
12
13
namespace PHPinnacle\Ensign;
14
15
final class Dispatcher
16
{
17
    /**
18
     * @var Processor
19
     */
20
    private $processor;
21
22
    /**
23
     * @var Arguments
24
     */
25
    private $resolver;
26
27
    /**
28
     * @var callable[]
29
     */
30
    private $handlers = [];
31
32
    /**
33
     * @param Processor $processor
34
     * @param Arguments $resolver
35
     */
36 7
    public function __construct(Processor $processor, Arguments $resolver)
37
    {
38 7
        $this->processor = $processor;
39 7
        $this->resolver  = $resolver;
40 7
    }
41
42
    /**
43
     * @param Arguments $resolver
44
     *
45
     * @return self
46
     */
47 7
    public static function amp(Arguments $resolver = null): self
48
    {
49 7
        return new self(new Amp\AmpProcessor(), $resolver ?: new Arguments\EmptyArguments());
50
    }
51
52
    /**
53
     * @param string   $signal
54
     * @param callable $handler
55
     *
56
     * @return self
57
     */
58 5
    public function register(string $signal, callable $handler): self
59
    {
60 5
        $this->handlers[$signal] = $handler;
61
62 5
        $this->processor->interrupt($signal, function (...$arguments) use ($signal) {
63 1
            return $this->dispatch($signal, ...$arguments);
64 5
        });
65
66 5
        return $this;
67
    }
68
69
    /**
70
     * {@inheritdoc}
71
     */
72 6
    public function dispatch($signal, ...$arguments): Task
73
    {
74 6
        if (\is_object($signal)) {
75 1
            \array_unshift($arguments, $signal);
76
77 1
            $signal = \get_class($signal);
78
        }
79
80 6
        $handler   = $this->handlers[$signal] ?? $this->error(new Exception\UnknownSignal($signal));
81 6
        $arguments = $this->resolve($handler, $arguments);
82
83 6
        return $this->processor->execute($handler, ...$arguments);
84
    }
85
86
    /**
87
     * @param callable $handler
88
     * @param array    $arguments
89
     *
90
     * @return array
91
     */
92 6
    private function resolve(callable $handler, array $arguments): array
93
    {
94 6
        $resolved = $this->resolver->resolve($handler);
95
96 6
        foreach ($resolved as $position => $argument) {
97 1
            \array_splice($arguments, $position, 0, [$argument]);
98
        }
99
100 6
        return $arguments;
101
    }
102
103
    /**
104
     * @param \Exception $exception
105
     *
106
     * @return callable
107
     */
108
    private function error(\Exception $exception): callable
109
    {
110 1
        return function () use ($exception) {
111 1
            throw $exception;
112 1
        };
113
    }
114
}
115